a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski/*
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * GRUB -- GRand Unified Bootloader
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * Copyright (c) 2013 Joyent, Inc. All rights reserved.
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski *
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * This program is free software; you can redistribute it and/or modify
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * it under the terms of the GNU General Public License as published by
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * the Free Software Foundation; either version 2 of the License, or
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * (at your option) any later version.
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski *
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * This program is distributed in the hope that it will be useful,
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * but WITHOUT ANY WARRANTY; without even the implied warranty of
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * GNU General Public License for more details.
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski *
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * You should have received a copy of the GNU General Public License
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * along with this program; if not, write to the Free Software
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski#include <expand.h>
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski#include <shared.h>
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski#ifdef SUPPORT_NETBOOT
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski#include <grub.h>
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski#endif
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski#include <cpu.h>
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski#define EVF_DEFINED 0x01
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski#define EVF_VALUESET 0x02
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskitypedef struct variable {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski char v_name[EV_NAMELEN];
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski unsigned int v_flags;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski char v_value[220]; /* 256 - EV_NAMELEN - sizeof (fields) */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski} variable_t;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskistatic variable_t expvars[32];
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskistatic const unsigned int nexpvars = 32;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskiint
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskiset_variable(const char *name, const char *value)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski{
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski unsigned int i;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski unsigned int avail = nexpvars;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (strlen(name) >= sizeof (expvars[0].v_name))
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (ERR_WONT_FIT);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (value != NULL && strlen(value) >= sizeof (expvars[0].v_value))
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (ERR_WONT_FIT);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski for (i = 0; i < nexpvars; i++) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (expvars[i].v_flags & EVF_DEFINED) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (grub_strcmp(expvars[i].v_name, name) == 0)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski break;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski } else if (i < avail) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski avail = i;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (i == nexpvars) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (avail == nexpvars)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (ERR_WONT_FIT);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski i = avail;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski (void) grub_strcpy(expvars[i].v_name, name);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski expvars[i].v_flags = EVF_DEFINED;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (value != NULL) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski (void) grub_strcpy(expvars[i].v_value, value);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski expvars[i].v_flags |= EVF_VALUESET;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski } else {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski expvars[i].v_flags &= ~EVF_VALUESET;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (0);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski}
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskiconst char *
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskiget_variable(const char *name)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski{
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski unsigned int i;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski for (i = 0; i < nexpvars; i++) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (!(expvars[i].v_flags & EVF_DEFINED))
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski continue;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (grub_strcmp(expvars[i].v_name, name) == 0) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (expvars[i].v_flags & EVF_VALUESET)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (expvars[i].v_value);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return ("");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (NULL);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski}
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskistatic int
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskidetect_target_operating_mode(void)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski{
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski int ret, ah;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski /*
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * This function returns 16 bits. The upper 8 are the value of %ah
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * after calling int 15/ec00. The lower 8 bits are zero if the BIOS
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * call left CF clear, nonzero otherwise.
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski ret = get_target_operating_mode();
7232236b5511ebe9b3343a5e1ab57a898e709218Andriy Gapon ah = ret >> 8;
7232236b5511ebe9b3343a5e1ab57a898e709218Andriy Gapon ret &= 0xff;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (ah == 0x86 && ret != 0) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("[BIOS 'Detect Target Operating Mode' "
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski "callback unsupported on this platform]\n");
7232236b5511ebe9b3343a5e1ab57a898e709218Andriy Gapon return (1); /* unsupported, ignore */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (ah == 0 && ret == 0) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("[BIOS accepted mixed-mode target setting!]\n");
7232236b5511ebe9b3343a5e1ab57a898e709218Andriy Gapon return (1); /* told the bios what we're up to */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (ah == 0 && ret != 0) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("fatal: BIOS reports this machine CANNOT run in "
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski "mixed 32/64-bit mode!\n");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (0);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("warning: BIOS Detect Target Operating Mode callback "
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski "confused.\n %%ax >> 8 = 0x%x, carry = %d\n", ah, ret);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (1);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski}
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskistatic int
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskiamd64_config_cpu(void)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski{
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski struct amd64_cpuid_regs __vcr, *vcr = &__vcr;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski uint32_t maxeax;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski uint32_t max_maxeax = 0x100;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski char vendor[13];
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski int isamd64 = 0;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski uint32_t stdfeatures = 0, xtdfeatures = 0;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski uint64_t efer;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski /*
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * This check may seem silly, but if the C preprocesor symbol __amd64
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * is #defined during compilation, something that may outwardly seem
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * like a good idea, uts/common/sys/isa_defs.h will #define _LP64,
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * which will cause uts/common/sys/int_types.h to typedef uint64_t as
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * an unsigned long - which is only 4 bytes in size when using a 32-bit
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * compiler.
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski *
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * If that happens, all the page table translation routines will fail
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * horribly, so check the size of uint64_t just to insure some degree
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * of sanity in future operations.
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski /*LINTED [sizeof result is invarient]*/
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (sizeof (uint64_t) != 8)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski prom_panic("grub compiled improperly, unable to boot "
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski "64-bit AMD64 executables");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski /*
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * If the CPU doesn't support the CPUID instruction, it's definitely
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * not an AMD64.
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (amd64_cpuid_supported() == 0)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (0);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski amd64_cpuid_insn(0, vcr);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski maxeax = vcr->r_eax;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski /*LINTED [vendor string from cpuid data]*/
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski uint32_t *iptr = (uint32_t *)vendor;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski *iptr++ = vcr->r_ebx;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski *iptr++ = vcr->r_edx;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski *iptr++ = vcr->r_ecx;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski vendor[12] = '\0';
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (maxeax > max_maxeax) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("cpu: warning, maxeax was 0x%x -> 0x%x\n",
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski maxeax, max_maxeax);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski maxeax = max_maxeax;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (maxeax < 1)
7232236b5511ebe9b3343a5e1ab57a898e709218Andriy Gapon return (0); /* no additional functions, not an AMD64 */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski else {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski uint_t family, model, step;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski amd64_cpuid_insn(1, vcr);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski /*
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * All AMD64/IA32e processors technically SHOULD report
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * themselves as being in family 0xf, but for some reason
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * Simics doesn't, and this may change in the future, so
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * don't error out if it's not true.
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if ((family = BITX(vcr->r_eax, 11, 8)) == 0xf)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski family += BITX(vcr->r_eax, 27, 20);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if ((model = BITX(vcr->r_eax, 7, 4)) == 0xf)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski model += BITX(vcr->r_eax, 19, 16) << 4;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski step = BITX(vcr->r_eax, 3, 0);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("cpu: '%s' family %d model %d step %d\n",
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski vendor, family, model, step);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski stdfeatures = vcr->r_edx;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski amd64_cpuid_insn(0x80000000, vcr);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (vcr->r_eax & 0x80000000) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski uint32_t xmaxeax = vcr->r_eax;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski const uint32_t max_xmaxeax = 0x80000100;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (xmaxeax > max_xmaxeax) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("amd64: warning, xmaxeax was "
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski "0x%x -> 0x%x\n", xmaxeax, max_xmaxeax);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski xmaxeax = max_xmaxeax;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (xmaxeax >= 0x80000001) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski amd64_cpuid_insn(0x80000001, vcr);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski xtdfeatures = vcr->r_edx;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
7232236b5511ebe9b3343a5e1ab57a898e709218Andriy Gapon if (BITX(xtdfeatures, 29, 29)) /* long mode */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski isamd64++;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski else
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("amd64: CPU does NOT support long mode\n");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (!BITX(stdfeatures, 0, 0)) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("amd64: CPU does NOT support FPU\n");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski isamd64--;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (!BITX(stdfeatures, 4, 4)) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("amd64: CPU does NOT support TSC\n");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski isamd64--;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (!BITX(stdfeatures, 5, 5)) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("amd64: CPU does NOT support MSRs\n");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski isamd64--;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (!BITX(stdfeatures, 6, 6)) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("amd64: CPU does NOT support PAE\n");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski isamd64--;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (!BITX(stdfeatures, 8, 8)) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("amd64: CPU does NOT support CX8\n");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski isamd64--;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (!BITX(stdfeatures, 13, 13)) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("amd64: CPU does NOT support PGE\n");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski isamd64--;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (!BITX(stdfeatures, 19, 19)) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("amd64: CPU does NOT support CLFSH\n");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski isamd64--;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (!BITX(stdfeatures, 23, 23)) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("amd64: CPU does NOT support MMX\n");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski isamd64--;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (!BITX(stdfeatures, 24, 24)) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("amd64: CPU does NOT support FXSR\n");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski isamd64--;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (!BITX(stdfeatures, 25, 25)) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("amd64: CPU does NOT support SSE\n");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski isamd64--;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (!BITX(stdfeatures, 26, 26)) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("amd64: CPU does NOT support SSE2\n");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski isamd64--;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (isamd64 < 1) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("amd64: CPU does not support amd64 executables.\n");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (0);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski amd64_rdmsr(MSR_AMD_EFER, &efer);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (efer & AMD_EFER_SCE)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("amd64: EFER_SCE (syscall/sysret) already "
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski "enabled\n");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (efer & AMD_EFER_NXE)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("amd64: EFER_NXE (no-exec prot) already enabled\n");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (efer & AMD_EFER_LME)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski grub_printf("amd64: EFER_LME (long mode) already enabled\n");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (detect_target_operating_mode());
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski}
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskistatic int
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskiisamd64()
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski{
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski static int ret = -1;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (ret == -1)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski ret = amd64_config_cpu();
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (ret);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski}
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskistatic int
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskicheck_min_mem64(void)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski{
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (min_mem64 == 0)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (1);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if ((mbi.mem_upper / 10240) * 11 >= min_mem64)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (1);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (0);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski}
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski/*
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * Given the nul-terminated input string s, expand all variable references
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * within that string into the buffer pointed to by d, which must be of length
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * not less than len bytes.
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski *
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * We also expand the special case tokens "$ISADIR" and "$ZFS-BOOTFS" here.
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski *
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * If the string will not fit, returns ERR_WONT_FIT.
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * If a nonexistent variable is referenced, returns ERR_NOVAR.
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * Otherwise, returns 0. The resulting string is nul-terminated. On error,
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * the contents of the destination buffer are undefined.
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskiint
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskiexpand_string(const char *s, char *d, unsigned int len)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski{
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski unsigned int i;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski int vlen;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski const char *p;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski char *q;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski const char *start;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski char name[EV_NAMELEN];
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski const char *val;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski for (p = s, q = d; *p != '\0' && q < d + len; ) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski /* Special case: $ISADIR */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (grub_strncmp(p, "$ISADIR", 7) == 0) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (isamd64() && check_min_mem64()) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (q + 5 >= d + len)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (ERR_WONT_FIT);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski (void) grub_memcpy(q, "amd64", 5);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski q += 5; /* amd64 */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski p += 7; /* $ISADIR */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski continue;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski /* Special case: $ZFS-BOOTFS */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (grub_strncmp(p, "$ZFS-BOOTFS", 11) == 0 &&
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski is_zfs_mount != 0) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (current_bootpath[0] == '\0' &&
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski current_devid[0] == '\0') {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (ERR_NO_BOOTPATH);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski /* zfs-bootfs=%s/%u */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski vlen = (current_bootfs_obj > 0) ? 10 : 0;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski vlen += 11;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski vlen += strlen(current_rootpool);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski /* ,bootpath=\"%s\" */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (current_bootpath[0] != '\0')
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski vlen += 12 + strlen(current_bootpath);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski /* ,diskdevid=\"%s\" */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (current_devid[0] != '\0')
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski vlen += 13 + strlen(current_devid);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (q + vlen >= d + len)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (ERR_WONT_FIT);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (current_bootfs_obj > 0) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski q += grub_sprintf(q, "zfs-bootfs=%s/%u",
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski current_rootpool, current_bootfs_obj);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski } else {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski q += grub_sprintf(q, "zfs-bootfs=%s",
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski current_rootpool);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (current_bootpath[0] != '\0') {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski q += grub_sprintf(q, ",bootpath=\"%s\"",
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski current_bootpath);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (current_devid[0] != '\0') {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski q += grub_sprintf(q, ",diskdevid=\"%s\"",
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski current_devid);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski p += 11; /* $ZFS-BOOTFS */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski continue;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (*p == '$' && *(p + 1) == '{') {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski start = p + 2;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski for (p = start; *p != '\0' && *p != '}' &&
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski p - start < sizeof (name) - 1; p++) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski name[p - start] = *p;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski /*
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski * Unterminated reference. Copy verbatim.
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski */
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (p - start >= sizeof (name) - 1 || *p != '}') {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski p = start;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski *q++ = '$';
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski *q++ = '{';
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski continue;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski name[p - start] = '\0';
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski val = get_variable(name);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (val == NULL)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (ERR_NOVAR);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if ((vlen = grub_strlen(val)) >= q + len - d)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (ERR_WONT_FIT);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski (void) grub_memcpy(q, val, vlen);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski q += vlen;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski p++;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski } else {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski *q++ = *p++;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (q >= d + len)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (ERR_WONT_FIT);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski *q = '\0';
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski return (0);
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski}
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskivoid
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowskidump_variables(void)
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski{
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski unsigned int i;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski for (i = 0; i < nexpvars; i++) {
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski if (!(expvars[i].v_flags & EVF_DEFINED))
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski continue;
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski (void) grub_printf("[%u] '%s' => '%s'\n", i, expvars[i].v_name,
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski (expvars[i].v_flags & EVF_VALUESET) ?
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski expvars[i].v_value : "");
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski }
a5602e1bdcf9570fa24684b54cf57a3f22e05ae1Keith M Wesolowski}