/* * Calculates the FSB and CPU frequencies using specific MSRs for each CPU * - multi. is read from a specific MSR. In the case of Intel, there is: * a max multi. (used to calculate the FSB freq.), * and a current multi. (used to calculate the CPU freq.) * - fsbFrequency = tscFrequency / multi * - cpuFrequency = fsbFrequency * multi */ void scan_cpu(PlatformInfo_t *p) { uint64_t tscFrequency, fsbFrequency, cpuFrequency; uint64_t msr, flex_ratio; uint8_t maxcoef, maxdiv, currcoef, bus_ratio_max, currdiv; const char *newratio; int len, myfsb; uint8_t bus_ratio_min; uint32_t max_ratio, min_ratio; max_ratio = min_ratio = myfsb = bus_ratio_min = 0; maxcoef = maxdiv = bus_ratio_max = currcoef = currdiv = 0; /* get cpuid values */ do_cpuid(0x00000000, p->CPU.CPUID[CPUID_0]); do_cpuid(0x00000001, p->CPU.CPUID[CPUID_1]); do_cpuid(0x00000002, p->CPU.CPUID[CPUID_2]); do_cpuid(0x00000003, p->CPU.CPUID[CPUID_3]); do_cpuid2(0x00000004, 0, p->CPU.CPUID[CPUID_4]); do_cpuid(0x80000000, p->CPU.CPUID[CPUID_80]); if (p->CPU.CPUID[CPUID_0][0] >= 0x5) { do_cpuid(5, p->CPU.CPUID[CPUID_5]); } if (p->CPU.CPUID[CPUID_0][0] >= 6) { do_cpuid(6, p->CPU.CPUID[CPUID_6]); } if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 8) { do_cpuid(0x80000008, p->CPU.CPUID[CPUID_88]); do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]); } else if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 1) { do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]); } #if DEBUG_CPU { int i; printf("CPUID Raw Values:\n"); for (i=0; i<CPUID_MAX; i++) { printf("%02d: %08x-%08x-%08x-%08x\n", i, p->CPU.CPUID[i][0], p->CPU.CPUID[i][1], p->CPU.CPUID[i][2], p->CPU.CPUID[i][3]); } } #endif p->CPU.Vendor = p->CPU.CPUID[CPUID_0][1]; p->CPU.Signature = p->CPU.CPUID[CPUID_1][0]; p->CPU.Stepping = bitfield(p->CPU.CPUID[CPUID_1][0], 3, 0); p->CPU.Model = bitfield(p->CPU.CPUID[CPUID_1][0], 7, 4); p->CPU.Family = bitfield(p->CPU.CPUID[CPUID_1][0], 11, 8); p->CPU.ExtModel = bitfield(p->CPU.CPUID[CPUID_1][0], 19, 16); p->CPU.ExtFamily = bitfield(p->CPU.CPUID[CPUID_1][0], 27, 20); p->CPU.Model += (p->CPU.ExtModel << 4); if (p->CPU.Vendor == CPUID_VENDOR_INTEL && p->CPU.Family == 0x06 && p->CPU.Model >= CPUID_MODEL_NEHALEM && p->CPU.Model != CPUID_MODEL_ATOM // MSR is *NOT* available on the Intel Atom CPU ) { msr = rdmsr64(MSR_CORE_THREAD_COUNT); // Undocumented MSR in Nehalem and newer CPUs p->CPU.NoCores = bitfield((uint32_t)msr, 31, 16); // Using undocumented MSR to get actual values p->CPU.NoThreads = bitfield((uint32_t)msr, 15, 0); // Using undocumented MSR to get actual values } else if (p->CPU.Vendor == CPUID_VENDOR_AMD) { p->CPU.NoThreads = bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16); p->CPU.NoCores = bitfield(p->CPU.CPUID[CPUID_88][2], 7, 0) + 1; } else { // Use previous method for Cores and Threads p->CPU.NoThreads = bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16); p->CPU.NoCores = bitfield(p->CPU.CPUID[CPUID_4][0], 31, 26) + 1; } /* get brand string (if supported) */ /* Copyright: from Apple's XNU cpuid.c */ if (p->CPU.CPUID[CPUID_80][0] > 0x80000004) { uint32_t reg[4]; char str[128], *s; /* * The brand string 48 bytes (max), guaranteed to * be NULL terminated. */ do_cpuid(0x80000002, reg); bcopy((char *)reg, &str[0], 16); do_cpuid(0x80000003, reg); bcopy((char *)reg, &str[16], 16); do_cpuid(0x80000004, reg); bcopy((char *)reg, &str[32], 16); for (s = str; *s != '\0'; s++) { if (*s != ' ') break; } strlcpy(p->CPU.BrandString, s, sizeof(p->CPU.BrandString)); if (!strncmp(p->CPU.BrandString, CPU_STRING_UNKNOWN, MIN(sizeof(p->CPU.BrandString), strlen(CPU_STRING_UNKNOWN) + 1))) { /* * This string means we have a firmware-programmable brand string, * and the firmware couldn't figure out what sort of CPU we have. */ p->CPU.BrandString[0] = '\0'; } } /* setup features */ if ((bit(23) & p->CPU.CPUID[CPUID_1][3]) != 0) { p->CPU.Features |= CPU_FEATURE_MMX; } if ((bit(25) & p->CPU.CPUID[CPUID_1][3]) != 0) { p->CPU.Features |= CPU_FEATURE_SSE; } if ((bit(26) & p->CPU.CPUID[CPUID_1][3]) != 0) { p->CPU.Features |= CPU_FEATURE_SSE2; } if ((bit(0) & p->CPU.CPUID[CPUID_1][2]) != 0) { p->CPU.Features |= CPU_FEATURE_SSE3; } if ((bit(19) & p->CPU.CPUID[CPUID_1][2]) != 0) { p->CPU.Features |= CPU_FEATURE_SSE41; } if ((bit(20) & p->CPU.CPUID[CPUID_1][2]) != 0) { p->CPU.Features |= CPU_FEATURE_SSE42; } if ((bit(29) & p->CPU.CPUID[CPUID_81][3]) != 0) { p->CPU.Features |= CPU_FEATURE_EM64T; } if ((bit(5) & p->CPU.CPUID[CPUID_1][3]) != 0) { p->CPU.Features |= CPU_FEATURE_MSR; } //if ((bit(28) & p->CPU.CPUID[CPUID_1][3]) != 0) { if (p->CPU.NoThreads > p->CPU.NoCores) { p->CPU.Features |= CPU_FEATURE_HTT; } tscFrequency = measure_tsc_frequency(); /* if usual method failed */ if ( tscFrequency < 1000 ) { tscFrequency = timeRDTSC() * 20; } fsbFrequency = 0; cpuFrequency = 0; if ((p->CPU.Vendor == CPUID_VENDOR_INTEL) && ((p->CPU.Family == 0x06) || (p->CPU.Family == 0x0f))) { int intelCPU = p->CPU.Model; if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0c) || (p->CPU.Family == 0x0f && p->CPU.Model >= 0x03)) { /* Nehalem CPU model */ if (p->CPU.Family == 0x06 && (p->CPU.Model == CPU_MODEL_NEHALEM || p->CPU.Model == CPU_MODEL_FIELDS || p->CPU.Model == CPU_MODEL_DALES || p->CPU.Model == CPU_MODEL_DALES_32NM || p->CPU.Model == CPU_MODEL_WESTMERE || p->CPU.Model == CPU_MODEL_NEHALEM_EX || p->CPU.Model == CPU_MODEL_WESTMERE_EX || p->CPU.Model == CPU_MODEL_SANDYBRIDGE || p->CPU.Model == CPU_MODEL_JAKETOWN || p->CPU.Model == CPU_MODEL_IVYBRIDGE)) { msr = rdmsr64(MSR_PLATFORM_INFO); DBG("msr(%d): platform_info %08x\n", __LINE__, bitfield(msr, 31, 0)); bus_ratio_max = bitfield(msr, 14, 8); bus_ratio_min = bitfield(msr, 46, 40); //valv: not sure about this one (Remarq.1) msr = rdmsr64(MSR_FLEX_RATIO); DBG("msr(%d): flex_ratio %08x\n", __LINE__, bitfield(msr, 31, 0)); if (bitfield(msr, 16, 16)) { flex_ratio = bitfield(msr, 14, 8); /* bcc9: at least on the gigabyte h67ma-ud2h, where the cpu multipler can't be changed to allow overclocking, the flex_ratio msr has unexpected (to OSX) contents. These contents cause mach_kernel to fail to compute the bus ratio correctly, instead causing the system to crash since tscGranularity is inadvertently set to 0. */ if (flex_ratio == 0) { /* Clear bit 16 (evidently the presence bit) */ wrmsr64(MSR_FLEX_RATIO, (msr & 0xFFFFFFFFFFFEFFFFULL)); msr = rdmsr64(MSR_FLEX_RATIO); verbose("Unusable flex ratio detected. Patched MSR now %08x\n", bitfield(msr, 31, 0)); } else { if (bus_ratio_max > flex_ratio) { bus_ratio_max = flex_ratio; } } } if (bus_ratio_max) { fsbFrequency = (tscFrequency / bus_ratio_max); } //valv: Turbo Ratio Limit if ((intelCPU != 0x2e) && (intelCPU != 0x2f)) { msr = rdmsr64(MSR_TURBO_RATIO_LIMIT); cpuFrequency = bus_ratio_max * fsbFrequency; max_ratio = bus_ratio_max * 10; } else { cpuFrequency = tscFrequency; } if ((getValueForKey(kbusratio, &newratio, &len, &bootInfo->chameleonConfig)) && (len <= 4)) { max_ratio = atoi(newratio); max_ratio = (max_ratio * 10); if (len >= 3) max_ratio = (max_ratio + 5); verbose("Bus-Ratio: min=%d, max=%s\n", bus_ratio_min, newratio); // extreme overclockers may love 320 ;) if ((max_ratio >= min_ratio) && (max_ratio <= 320)) { cpuFrequency = (fsbFrequency * max_ratio) / 10; if (len >= 3) maxdiv = 1; else maxdiv = 0; } else { max_ratio = (bus_ratio_max * 10); } } //valv: to be uncommented if Remarq.1 didn't stick /*if (bus_ratio_max > 0) bus_ratio = flex_ratio;*/ p->CPU.MaxRatio = max_ratio; p->CPU.MinRatio = min_ratio; myfsb = fsbFrequency / 1000000; verbose("Sticking with [BCLK: %dMhz, Bus-Ratio: %d]\n", myfsb, max_ratio); currcoef = bus_ratio_max; } else { msr = rdmsr64(MSR_IA32_PERF_STATUS); DBG("msr(%d): ia32_perf_stat 0x%08x\n", __LINE__, bitfield(msr, 31, 0)); currcoef = bitfield(msr, 12, 8); /* Non-integer bus ratio for the max-multi*/ maxdiv = bitfield(msr, 46, 46); /* Non-integer bus ratio for the current-multi (undocumented)*/ currdiv = bitfield(msr, 14, 14); // This will always be model >= 3 if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0e) || (p->CPU.Family == 0x0f)) { /* On these models, maxcoef defines TSC freq */ maxcoef = bitfield(msr, 44, 40); } else { /* On lower models, currcoef defines TSC freq */ /* XXX */ maxcoef = currcoef; } if (maxcoef) { if (maxdiv) { fsbFrequency = ((tscFrequency * 2) / ((maxcoef * 2) + 1)); } else { fsbFrequency = (tscFrequency / maxcoef); } if (currdiv) { cpuFrequency = (fsbFrequency * ((currcoef * 2) + 1) / 2); } else { cpuFrequency = (fsbFrequency * currcoef); } DBG("max: %d%s current: %d%s\n", maxcoef, maxdiv ? ".5" : "",currcoef, currdiv ? ".5" : ""); } } } /* Mobile CPU */ if (rdmsr64(MSR_IA32_PLATFORM_ID) & (1<<28)) { p->CPU.Features |= CPU_FEATURE_MOBILE; } } else if ((p->CPU.Vendor == CPUID_VENDOR_AMD) && (p->CPU.Family == 0x0f)) { switch(p->CPU.ExtFamily) { case 0x00: /* K8 */ msr = rdmsr64(K8_FIDVID_STATUS); maxcoef = bitfield(msr, 21, 16) / 2 + 4; currcoef = bitfield(msr, 5, 0) / 2 + 4; break; case 0x01: /* K10 */ msr = rdmsr64(K10_COFVID_STATUS); do_cpuid2(0x00000006, 0, p->CPU.CPUID[CPUID_6]); // EffFreq: effective frequency interface if (bitfield(p->CPU.CPUID[CPUID_6][2], 0, 0) == 1) { //uint64_t mperf = measure_mperf_frequency(); uint64_t aperf = measure_aperf_frequency(); cpuFrequency = aperf; } // NOTE: tsc runs at the maccoeff (non turbo) // *not* at the turbo frequency. maxcoef = bitfield(msr, 54, 49) / 2 + 4; currcoef = bitfield(msr, 5, 0) + 0x10; currdiv = 2 << bitfield(msr, 8, 6); break; case 0x05: /* K14 */ msr = rdmsr64(K10_COFVID_STATUS); currcoef = (bitfield(msr, 54, 49) + 0x10) << 2; currdiv = (bitfield(msr, 8, 4) + 1) << 2; currdiv += bitfield(msr, 3, 0); break; case 0x02: /* K11 */ // not implimented break; } if (maxcoef) { if (currdiv) { if (!currcoef) currcoef = maxcoef; if (!cpuFrequency) fsbFrequency = ((tscFrequency * currdiv) / currcoef); else fsbFrequency = ((cpuFrequency * currdiv) / currcoef); DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv); } else { if (!cpuFrequency) fsbFrequency = (tscFrequency / maxcoef); else fsbFrequency = (cpuFrequency / maxcoef); DBG("%d\n", currcoef); } } else if (currcoef) { if (currdiv) { fsbFrequency = ((tscFrequency * currdiv) / currcoef); DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv); } else { fsbFrequency = (tscFrequency / currcoef); DBG("%d\n", currcoef); } } if (!cpuFrequency) cpuFrequency = tscFrequency; } #if 0 if (!fsbFrequency) { fsbFrequency = (DEFAULT_FSB * 1000); cpuFrequency = tscFrequency; DBG("0 ! using the default value for FSB !\n"); } #endif p->CPU.MaxCoef = maxcoef; p->CPU.MaxDiv = maxdiv; p->CPU.CurrCoef = currcoef; p->CPU.CurrDiv = currdiv; p->CPU.TSCFrequency = tscFrequency; p->CPU.FSBFrequency = fsbFrequency; p->CPU.CPUFrequency = cpuFrequency; // keep formatted with spaces instead of tabs DBG("CPU: Brand String: %s\n", p->CPU.BrandString); DBG("CPU: Vendor/Family/ExtFamily: 0x%x/0x%x/0x%x\n", p->CPU.Vendor, p->CPU.Family, p->CPU.ExtFamily); DBG("CPU: Model/ExtModel/Stepping: 0x%x/0x%x/0x%x\n", p->CPU.Model, p->CPU.ExtModel, p->CPU.Stepping); DBG("CPU: MaxCoef/CurrCoef: 0x%x/0x%x\n", p->CPU.MaxCoef, p->CPU.CurrCoef); DBG("CPU: MaxDiv/CurrDiv: 0x%x/0x%x\n", p->CPU.MaxDiv, p->CPU.CurrDiv); DBG("CPU: TSCFreq: %dMHz\n", p->CPU.TSCFrequency / 1000000); DBG("CPU: FSBFreq: %dMHz\n", p->CPU.FSBFrequency / 1000000); DBG("CPU: CPUFreq: %dMHz\n", p->CPU.CPUFrequency / 1000000); DBG("CPU: NoCores/NoThreads: %d/%d\n", p->CPU.NoCores, p->CPU.NoThreads); DBG("CPU: Features: 0x%08x\n", p->CPU.Features); #if DEBUG_CPU pause(); #endif }
BVRef selectBootVolume( BVRef chain ) { bool filteredChain = false; bool foundPrimary = false; BVRef bvr, bvr1 = 0, bvr2 = 0; if (chain->filtered) filteredChain = true; if (multiboot_partition_set) for ( bvr = chain; bvr; bvr = bvr->next ) if ( bvr->part_no == multiboot_partition && bvr->biosdev == gBIOSDev ) return bvr; /* * Checking "Default Partition" key in system configuration - use format: hd(x,y) - * to override the default selection. */ const char * val; char testStr[64]; int cnt; if (getValueForKey(kDefaultPartition, &val, &cnt, &bootInfo->bootConfig) && cnt >= 7 && filteredChain) { for ( bvr = chain; bvr; bvr = bvr->next ) { *testStr = '\0'; if ( bvr->biosdev >= 0x80 && bvr->biosdev < 0x100 ) { sprintf(testStr, "hd(%d,%d)", bvr->biosdev - 0x80, bvr->part_no); if (strcmp(testStr, val) == 0) return bvr; } } } /* * Scannig the volume chain backwards and trying to find * a HFS+ volume with valid boot record signature. * If not found any active partition then we will * select this volume as the boot volume. */ for ( bvr = chain; bvr; bvr = bvr->next ) { if ( bvr->flags & kBVFlagPrimary && bvr->biosdev == gBIOSDev ) foundPrimary = true; // zhell -- Undo a regression that was introduced from r491 to 492. // if gBIOSBootVolume is set already, no change is required if ( bvr->flags & (kBVFlagBootable|kBVFlagSystemVolume) && gBIOSBootVolume && (!filteredChain || (filteredChain && bvr->visible)) && bvr->biosdev == gBIOSDev ) bvr2 = bvr; // zhell -- if gBIOSBootVolume is NOT set, we use the "if" statement // from r491, if ( bvr->flags & kBVFlagBootable && ! gBIOSBootVolume && bvr->biosdev == gBIOSDev ) bvr2 = bvr; } /* * Use the standrad method for selecting the boot volume. */ if (foundPrimary) { for ( bvr = chain; bvr; bvr = bvr->next ) { if ( bvr->flags & kBVFlagNativeBoot && bvr->biosdev == gBIOSDev ) bvr1 = bvr; if ( bvr->flags & kBVFlagPrimary && bvr->biosdev == gBIOSDev ) bvr2 = bvr; } } bvr = bvr2 ? bvr2 : bvr1 ? bvr1 : chain; return bvr; }
int initGUI(void) { int val; #ifdef EMBED_THEME config_file_t *config; config = &bootInfo->themeConfig; if (ParseXMLFile((char *)__theme_plist, &config->dictionary) != 0) { return 1; } #else int len; char dirspec[256]; getValueForKey( "Theme", &theme_name, &len, &bootInfo->bootConfig ); if ((strlen(theme_name) + 27) > sizeof(dirspec)) { return 1; } sprintf(dirspec, "/Extra/Themes/%s/theme.plist", theme_name); if (loadConfigFile(dirspec, &bootInfo->themeConfig) != 0) { return 1; } #endif // parse display size parameters if (getIntForKey("screen_width", &val, &bootInfo->themeConfig)) { screen_params[0] = val; } if (getIntForKey("screen_height", &val, &bootInfo->themeConfig)) { screen_params[1] = val; } screen_params[2] = 32; // Initalizing GUI strucutre. bzero(&gui, sizeof(gui_t)); // find best matching vesa mode for our requested width & height getGraphicModeParams(screen_params); // set our screen structure with the mode width & height gui.screen.width = screen_params[0]; gui.screen.height = screen_params[1]; // load graphics otherwise fail and return if (loadGraphics() == 0) { loadThemeValues(&bootInfo->themeConfig, true); colorFont(&font_small, gui.screen.font_small_color); colorFont(&font_console, gui.screen.font_console_color); // create the screen & window buffers if (createBackBuffer(&gui.screen) == 0) { if (createWindowBuffer(&gui.screen) == 0) { if (createWindowBuffer(&gui.devicelist) == 0) { if (createWindowBuffer(&gui.bootprompt) == 0) { if (createWindowBuffer(&gui.infobox) == 0) { if (createWindowBuffer(&gui.menu) == 0) { drawBackground(); // lets copy the screen into the back buffer memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 ); setVideoMode( GRAPHICS_MODE, 0 ); gui.initialised = true; return 0; } } } } } } } return 1; }
/** From the origsmbios detected by getAddressOfSmbiosTable() to newsmbios whose entrypoint * struct has been created by smbios_dry_run, update each table struct content of new smbios * int the new allocated table address of size newsmbios->tablelength. */ static void smbios_real_run(struct SMBEntryPoint * origsmbios, struct SMBEntryPoint * newsmbios) { char *smbiostables; char *tablesptr, *newtablesptr; int origsmbiosnum; // bitmask of used handles uint8_t handles[8192]; uint16_t nexthandle=0; int i, j; int tablespresent[256]; bool do_auto=true; extern void dumpPhysAddr(const char * title, void * a, int len); bzero(tablespresent, sizeof(tablespresent)); bzero(handles, sizeof(handles)); getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig); newsmbios->dmi.tableAddress = (uint32_t)AllocateKernelMemory(newsmbios->dmi.tableLength); if (origsmbios) { smbiostables = (char *)origsmbios->dmi.tableAddress; origsmbiosnum = origsmbios->dmi.structureCount; } else { smbiostables = NULL; origsmbiosnum = 0; } tablesptr = smbiostables; newtablesptr = (char *)newsmbios->dmi.tableAddress; // if old smbios exists then update new smbios with old smbios original content first if (smbiostables) { for (i=0; i<origsmbiosnum; i++) { struct smbios_table_header *oldcur = (struct smbios_table_header *) tablesptr; struct smbios_table_header *newcur = (struct smbios_table_header *) newtablesptr; char *stringsptr; int nstrings = 0; handles[(oldcur->handle) / 8] |= 1 << ((oldcur->handle) % 8); // copy table length from old table to new table but not the old strings memcpy(newcur,oldcur, oldcur->length); tablesptr += oldcur->length; stringsptr = tablesptr; newtablesptr += oldcur->length; // calculate the number of strings in the old content for (;tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++) { if (tablesptr[0] == 0) { nstrings++; } } if (tablesptr != stringsptr) { nstrings++; } tablesptr += 2; // copy the old strings to new table memcpy(newtablesptr, stringsptr, tablesptr-stringsptr); // point to next possible space for a string (deducting the second 0 char at the end) newtablesptr += tablesptr - stringsptr - 1; if (nstrings == 0) { // if no string was found rewind to the first 0 char of the 0,0 terminator newtablesptr--; } // now for each property in the table update the overrides if any (auto or user) for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) { const char *str; int size; int num; char altname[40]; sprintf(altname, "%s_%d", smbios_properties[j].name, tablespresent[newcur->type] + 1); if (smbios_properties[j].table_type == newcur->type) { switch (smbios_properties[j].value_type) { case SMSTRING: if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) || getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)) { memcpy(newtablesptr, str, size); newtablesptr[size] = 0; newtablesptr += size + 1; *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings; } else if (do_auto && smbios_properties[j].auto_str) { str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]); size = strlen(str); memcpy(newtablesptr, str, size); newtablesptr[size] = 0; newtablesptr += size + 1; *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings; } break; case SMOWORD: if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) || getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)) { int k=0, t=0, kk=0; const char *ptr = str; memset(((char*)newcur) + smbios_properties[j].offset, 0, 16); while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) { ptr++; } if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) { ptr += 2; } for (;ptr-str<size && *ptr && k<16;ptr++) { if (*ptr>='0' && *ptr<='9') { (t=(t<<4)|(*ptr-'0')),kk++; } if (*ptr>='a' && *ptr<='f') { (t=(t<<4)|(*ptr-'a'+10)),kk++; } if (*ptr>='A' && *ptr<='F') { (t=(t<<4)|(*ptr-'A'+10)),kk++; } if (kk == 2) { *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t; k++; kk = 0; t = 0; } } } break; case SMBYTE: if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) || getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig)) { *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num; } else if (do_auto && smbios_properties[j].auto_int) { *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); } break; case SMWORD: if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) || getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig)) { *((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num; } else if (do_auto && smbios_properties[j].auto_int) { *((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); } break; } } } if (nstrings == 0) { newtablesptr[0] = 0; newtablesptr++; } newtablesptr[0] = 0; newtablesptr++; tablespresent[newcur->type]++; } } // for each eventual complementary table not present in the original smbios, do the overrides for (i=0; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) { int numnec = -1; char buffer[40]; sprintf(buffer, "SMtable%d", i); if (!getIntForKey(buffer, &numnec, &bootInfo->smbiosConfig)) { numnec = -1; } if (numnec == -1 && do_auto && smbios_table_descriptions[i].numfunc) { numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type); } while (tablespresent[smbios_table_descriptions[i].type] < numnec) { struct smbios_table_header *newcur = (struct smbios_table_header *) newtablesptr; int nstrings = 0; memset(newcur,0, smbios_table_descriptions[i].len); while (handles[(nexthandle)/8] & (1 << ((nexthandle) % 8))) { nexthandle++; } newcur->handle = nexthandle; handles[nexthandle / 8] |= 1 << (nexthandle % 8); newcur->type = smbios_table_descriptions[i].type; newcur->length = smbios_table_descriptions[i].len; newtablesptr += smbios_table_descriptions[i].len; for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) { const char *str; int size; int num; char altname[40]; sprintf(altname, "%s_%d", smbios_properties[j].name, tablespresent[newcur->type] + 1); if (smbios_properties[j].table_type == newcur->type) { switch (smbios_properties[j].value_type) { case SMSTRING: if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) || getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)) { memcpy(newtablesptr, str, size); newtablesptr[size] = 0; newtablesptr += size + 1; *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings; } else if (do_auto && smbios_properties[j].auto_str) { str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]); size = strlen(str); memcpy(newtablesptr, str, size); newtablesptr[size] = 0; newtablesptr += size + 1; *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings; } break; case SMOWORD: if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) || getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)) { int k=0, t=0, kk=0; const char *ptr = str; memset(((char*)newcur) + smbios_properties[j].offset, 0, 16); while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) { ptr++; } if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) { ptr += 2; } for (;ptr-str<size && *ptr && k<16;ptr++) { if (*ptr>='0' && *ptr<='9') { (t=(t<<4)|(*ptr-'0')),kk++; } if (*ptr>='a' && *ptr<='f') { (t=(t<<4)|(*ptr-'a'+10)),kk++; } if (*ptr>='A' && *ptr<='F') { (t=(t<<4)|(*ptr-'A'+10)),kk++; } if (kk == 2) { *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t; k++; kk = 0; t = 0; } } } break; case SMBYTE: if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) || getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig)) { *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num; } else if (do_auto && smbios_properties[j].auto_int) { *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); } break; case SMWORD: if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) || getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig)) { *((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num; } else if (do_auto && smbios_properties[j].auto_int) { *((uint16_t*)(((char*)newcur)+smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); } break; } } } if (nstrings == 0) { newtablesptr[0] = 0; newtablesptr++; } newtablesptr[0] = 0; newtablesptr++; tablespresent[smbios_table_descriptions[i].type]++; } } // calculate new checksums newsmbios->dmi.checksum = 0; newsmbios->dmi.checksum = 256 - checksum8(&newsmbios->dmi, sizeof(newsmbios->dmi)); newsmbios->checksum = 0; newsmbios->checksum = 256 - checksum8(newsmbios, sizeof(*newsmbios)); verbose("Patched DMI Table\n"); }
void smbios_real_run (struct SMBEntryPoint * origsmbios, struct SMBEntryPoint * newsmbios) { char *smbiostables=0; char *tablesptr, *newtablesptr; int origsmbiosnum=0; // bitmask of used handles uint8_t handles[8192]; uint16_t nexthandle=0; int i, j; int tablespresent[256]; BOOL do_auto=1; getBoolForKey("SMBIOSdefaults",&do_auto,&bootInfo->bootConfig); for (i=0;i<256;i++) tablespresent[i]=0; memset (handles,0,8192); newsmbios->dmi.tableAddress=(uint32_t)AllocateKernelMemory(newsmbios->dmi.tableLength); if (origsmbios) { smbiostables=(char *) origsmbios->dmi.tableAddress; origsmbiosnum=origsmbios->dmi.structureCount; } tablesptr=smbiostables; newtablesptr=(char *) newsmbios->dmi.tableAddress; if (smbiostables) for (i=0;i<origsmbiosnum;i++) { struct smbios_table_header *oldcur =(struct smbios_table_header *) tablesptr, *newcur=(struct smbios_table_header *) newtablesptr; char *stringsptr; int nstrings=0; handles[(oldcur->handle)/8]|=1<<((oldcur->handle)%8); memcpy (newcur,oldcur, oldcur->length); tablesptr+=oldcur->length; stringsptr=tablesptr; newtablesptr+=oldcur->length; for (;tablesptr[0]!=0 || tablesptr[1]!=0;tablesptr++) if (tablesptr[0]==0) nstrings++; if (tablesptr!=stringsptr) nstrings++; tablesptr+=2; memcpy (newtablesptr,stringsptr,tablesptr-stringsptr); //point to next possible space for a string newtablesptr+=tablesptr-stringsptr-1; if (nstrings==0) newtablesptr--; for (j=0;j<sizeof (smbios_properties)/sizeof(smbios_properties[0]); j++) { const char *str; int size; int num; char altname[40]; sprintf (altname, "%s_%d",smbios_properties[j].name, tablespresent[newcur->type]+1); if (smbios_properties[j].table_type==newcur->type) switch (smbios_properties[j].value_type) { case SMSTRING: if (getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig) ||getValueForKey(smbios_properties[j].name,&str, &size, &bootInfo->smbiosConfig)) { memcpy (newtablesptr, str,size); newtablesptr[size]=0; newtablesptr+=size+1; *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))=++nstrings; } else if (do_auto && smbios_properties[j].auto_str) { str=smbios_properties[j].auto_str(smbios_properties[j].name,tablespresent[newcur->type]); size=strlen (str); memcpy (newtablesptr, str,size); newtablesptr[size]=0; newtablesptr+=size+1; *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))=++nstrings; } break; case SMOWORD: if (getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig) ||getValueForKey(smbios_properties[j].name,&str, &size, &bootInfo->smbiosConfig)) { int k=0, t=0, kk=0; const char *ptr=str; memset(((char*)newcur)+smbios_properties[j].offset, 0, 16); while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) ptr++; if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) ptr+=2; for (;ptr-str<size && *ptr && k<16;ptr++) { if (*ptr>='0' && *ptr<='9') (t=(t<<4)|(*ptr-'0')),kk++; if (*ptr>='a' && *ptr<='f') (t=(t<<4)|(*ptr-'a'+10)),kk++; if (*ptr>='A' && *ptr<='F') (t=(t<<4)|(*ptr-'A'+10)),kk++; if (kk==2) { *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset+k))=t; k++; kk=0; t=0; } } } break; case SMBYTE: if (getIntForKey(altname,&num,&bootInfo->smbiosConfig) ||getIntForKey(smbios_properties[j].name,&num,&bootInfo->smbiosConfig)) *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))=num; else if (do_auto && smbios_properties[j].auto_int) *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset)) =smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); break; case SMWORD: if (getIntForKey(altname,&num,&bootInfo->smbiosConfig) ||getIntForKey(smbios_properties[j].name,&num,&bootInfo->smbiosConfig)) *((uint16_t*)(((char*)newcur)+smbios_properties[j].offset))=num; else if (do_auto && smbios_properties[j].auto_int) *((uint16_t*)(((char*)newcur)+smbios_properties[j].offset)) =smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); break; } } if (nstrings==0) { newtablesptr[0]=0; newtablesptr++; } newtablesptr[0]=0; newtablesptr++; tablespresent[newcur->type]++; } for (i=0;i<sizeof (smbios_table_descriptions) /sizeof(smbios_table_descriptions[0]);i++) { int numnec=-1; char buffer[40]; sprintf (buffer, "SMtable%d", i); if (!getIntForKey(buffer,&numnec,&bootInfo->smbiosConfig)) numnec=-1; if (numnec==-1 && do_auto && smbios_table_descriptions[i].numfunc) numnec=smbios_table_descriptions[i].numfunc (smbios_table_descriptions[i].type); while (tablespresent[smbios_table_descriptions[i].type]<numnec) { struct smbios_table_header *newcur=(struct smbios_table_header *) newtablesptr; int nstrings=0; memset (newcur,0, smbios_table_descriptions[i].len); while (handles[(nexthandle)/8]&(1<<((nexthandle)%8))) nexthandle++; newcur->handle=nexthandle; handles[nexthandle/8]|=1<<(nexthandle%8); newcur->type=smbios_table_descriptions[i].type; newcur->length=smbios_table_descriptions[i].len; newtablesptr+=smbios_table_descriptions[i].len; for (j=0;j<sizeof (smbios_properties)/sizeof(smbios_properties[0]); j++) { const char *str; int size; int num; char altname[40]; sprintf (altname, "%s_%d",smbios_properties[j].name, tablespresent[newcur->type]+1); if (smbios_properties[j].table_type==newcur->type) switch (smbios_properties[j].value_type) { case SMSTRING: if (getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig) ||getValueForKey(smbios_properties[j].name,&str, &size, &bootInfo->smbiosConfig)) { memcpy (newtablesptr, str,size); newtablesptr[size]=0; newtablesptr+=size+1; *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))=++nstrings; } else if (do_auto && smbios_properties[j].auto_str) { str=smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]); size=strlen (str); memcpy (newtablesptr, str,size); newtablesptr[size]=0; newtablesptr+=size+1; *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))=++nstrings; } break; case SMOWORD: if (getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig) ||getValueForKey(smbios_properties[j].name,&str, &size, &bootInfo->smbiosConfig)) { int k=0, t=0, kk=0; const char *ptr=str; memset(((char*)newcur)+smbios_properties[j].offset, 0, 16); while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) ptr++; if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) ptr+=2; for (;ptr-str<size && *ptr && k<16;ptr++) { if (*ptr>='0' && *ptr<='9') (t=(t<<4)|(*ptr-'0')),kk++; if (*ptr>='a' && *ptr<='f') (t=(t<<4)|(*ptr-'a'+10)),kk++; if (*ptr>='A' && *ptr<='F') (t=(t<<4)|(*ptr-'A'+10)),kk++; if (kk==2) { *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset+k))=t; k++; kk=0; t=0; } } } break; case SMBYTE: if (getIntForKey(altname,&num,&bootInfo->smbiosConfig) ||getIntForKey(smbios_properties[j].name,&num,&bootInfo->smbiosConfig)) *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))=num; else if (do_auto && smbios_properties[j].auto_int) *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset)) =smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); break; case SMWORD: if (getIntForKey(altname,&num,&bootInfo->smbiosConfig) ||getIntForKey(smbios_properties[j].name,&num,&bootInfo->smbiosConfig)) *((uint16_t*)(((char*)newcur)+smbios_properties[j].offset))=num; else if (do_auto && smbios_properties[j].auto_int) *((uint16_t*)(((char*)newcur)+smbios_properties[j].offset)) =smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); break; } } if (nstrings==0) { newtablesptr[0]=0; newtablesptr++; } newtablesptr[0]=0; newtablesptr++; tablespresent[smbios_table_descriptions[i].type]++; } } newsmbios->dmi.checksum=0; newsmbios->dmi.checksum=256-checksum8 (&newsmbios->dmi,sizeof (newsmbios->dmi)); newsmbios->checksum=0; newsmbios->checksum=256-checksum8 (newsmbios,sizeof (*newsmbios)); verbose("Patched DMI Table.\n"); }
int getBootOptions(bool firstRun) { int i; int key; int nextRow; int timeout; int bvCount; BVRef bvr; BVRef menuBVR; bool showPrompt, newShowPrompt, isCDROM; // Initialize default menu selection entry. gBootVolume = menuBVR = selectBootVolume(bvChain); if (biosDevIsCDROM(gBIOSDev)) { isCDROM = true; } else { isCDROM = false; } // ensure we're in graphics mode if gui is setup if (firstRun && gui.initialised && bootArgs->Video.v_display == VGA_TEXT_MODE) { setVideoMode(GRAPHICS_MODE, 0); } // Clear command line boot arguments clearBootArgs(); // Allow user to override default timeout. if (multiboot_timeout_set) { timeout = multiboot_timeout; } else if (!getIntForKey(kTimeoutKey, &timeout, &bootInfo->chameleonConfig)) { /* If there is no timeout key in the file use the default timeout which is different for CDs vs. hard disks. However, if not booting a CD and no config file could be loaded set the timeout to zero which causes the menu to display immediately. This way, if no partitions can be found, that is the disk is unpartitioned or simply cannot be read) then an empty menu is displayed. If some partitions are found, for example a Windows partition, then these will be displayed in the menu as foreign partitions. */ if (isCDROM) { timeout = kCDBootTimeout; } else { timeout = sysConfigValid ? kBootTimeout : 0; } } if (timeout < 0) { gBootMode |= kBootModeQuiet; } // If the user is holding down a modifier key, enter safe mode. if ((readKeyboardShiftFlags() & 0x0F) != 0) { gBootMode |= kBootModeSafe; } // Checking user pressed keys bool f8press = false, spress = false, vpress = false; while (readKeyboardStatus()) { key = bgetc (); if (key == 0x4200) f8press = true; if ((key & 0xff) == 's' || (key & 0xff) == 'S') spress = true; if ((key & 0xff) == 'v' || (key & 0xff) == 'V') vpress = true; } // If user typed F8, abort quiet mode, and display the menu. if (f8press) { gBootMode &= ~kBootModeQuiet; timeout = 0; } // If user typed 'v' or 'V', boot in verbose mode. if ((gBootMode & kBootModeQuiet) && firstRun && vpress) { addBootArg(kVerboseModeFlag); } // If user typed 's' or 'S', boot in single user mode. if ((gBootMode & kBootModeQuiet) && firstRun && spress) { addBootArg(kSingleUserModeFlag); } if (bootArgs->Video.v_display == VGA_TEXT_MODE) { setCursorPosition(0, 0, 0); clearScreenRows(0, kScreenLastRow); if (!(gBootMode & kBootModeQuiet)) { // Display banner and show hardware info. printf(bootBanner, (bootInfo->convmem + bootInfo->extmem) / 1024); printf(getVBEInfoString()); } changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0); verbose("Scanning device %x...", gBIOSDev); } // When booting from CD, default to hard drive boot when possible. if (isCDROM && firstRun) { const char *val; char *prompt = NULL; char *name = NULL; int cnt; int optionKey; if (getValueForKey(kCDROMPromptKey, &val, &cnt, &bootInfo->chameleonConfig)) { prompt = malloc(cnt + 1); strncat(prompt, val, cnt); } else { name = malloc(80); getBootVolumeDescription(gBootVolume, name, 79, false); prompt = malloc(256); sprintf(prompt, "Press any key to start up from %s, or press F8 to enter startup options.", name); free(name); } if (getIntForKey( kCDROMOptionKey, &optionKey, &bootInfo->chameleonConfig )) { // The key specified is a special key. } else { // Default to F8. optionKey = 0x4200; } // If the timeout is zero then it must have been set above due to the // early catch of F8 which means the user wants to set boot options // which we ought to interpret as meaning he wants to boot the CD. if (timeout != 0) { key = countdown(prompt, kMenuTopRow, timeout); } else { key = optionKey; } if (prompt != NULL) { free(prompt); } clearScreenRows( kMenuTopRow, kMenuTopRow + 2 ); // Hit the option key ? if (key == optionKey) { gBootMode &= ~kBootModeQuiet; timeout = 0; } else { key = key & 0xFF; // Try booting hard disk if user pressed 'h' if (biosDevIsCDROM(gBIOSDev) && key == 'h') { BVRef bvr; // Look at partitions hosting OS X other than the CD-ROM for (bvr = bvChain; bvr; bvr=bvr->next) { if ((bvr->flags & kBVFlagSystemVolume) && bvr->biosdev != gBIOSDev) { gBootVolume = bvr; } } } goto done; } } if (gBootMode & kBootModeQuiet) { // No input allowed from user. goto done; } if (firstRun && timeout > 0 && countdown("Press any key to enter startup options.", kMenuTopRow, timeout) == 0) { // If the user is holding down a modifier key, // enter safe mode. if ((readKeyboardShiftFlags() & 0x0F) != 0) { gBootMode |= kBootModeSafe; } goto done; } if (gDeviceCount) { // Allocate memory for an array of menu items. menuItems = malloc(sizeof(MenuItem) * gDeviceCount); if (menuItems == NULL) { goto done; } // Associate a menu item for each BVRef. for (bvr=bvChain, i=gDeviceCount-1, selectIndex=0; bvr; bvr=bvr->next) { if (bvr->visible) { getBootVolumeDescription(bvr, menuItems[i].name, sizeof(menuItems[i].name) - 1, true); menuItems[i].param = (void *) bvr; if (bvr == menuBVR) { selectIndex = i; } i--; } } } if (bootArgs->Video.v_display != VGA_TEXT_MODE) { // redraw the background buffer gui.logo.draw = true; drawBackground(); gui.devicelist.draw = true; gui.redraw = true; if (!(gBootMode & kBootModeQuiet)) { // Check if "Boot Banner"=N switch is present in config file. getBoolForKey(kBootBannerKey, &showBootBanner, &bootInfo->chameleonConfig); if (showBootBanner) { // Display banner and show hardware info. gprintf(&gui.screen, bootBanner + 1, (bootInfo->convmem + bootInfo->extmem) / 1024); } // redraw background memcpy(gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4); } } else { // Clear screen and hide the blinking cursor. clearScreenRows(kMenuTopRow, kMenuTopRow + 2); changeCursor(0, kMenuTopRow, kCursorTypeHidden, 0); } nextRow = kMenuTopRow; showPrompt = true; if (gDeviceCount) { if( bootArgs->Video.v_display == VGA_TEXT_MODE ) { printf("Use \30\31 keys to select the startup volume."); } showMenu( menuItems, gDeviceCount, selectIndex, kMenuTopRow + 2, kMenuMaxItems ); nextRow += MIN( gDeviceCount, kMenuMaxItems ) + 3; } // Show the boot prompt. showPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot); showBootPrompt( nextRow, showPrompt ); do { if (bootArgs->Video.v_display != VGA_TEXT_MODE) { // redraw background memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 ); // reset cursor co-ords gui.debug.cursor = pos( gui.screen.width - 160 , 10 ); } key = getchar(); updateMenu( key, (void **) &menuBVR ); newShowPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot); if (newShowPrompt != showPrompt) { showPrompt = newShowPrompt; showBootPrompt( nextRow, showPrompt ); } if (showPrompt) { updateBootArgs(key); } switch (key) { case kReturnKey: if (gui.menu.draw) { key=0; break; } if (*gBootArgs == '?') { char * argPtr = gBootArgs; // Skip the leading "?" character. argPtr++; getNextArg(&argPtr, booterCommand); getNextArg(&argPtr, booterParam); /* * TODO: this needs to be refactored. */ if (strcmp( booterCommand, "video" ) == 0) { if (bootArgs->Video.v_display != VGA_TEXT_MODE) { showInfoBox(getVBEInfoString(), getVBEModeInfoString()); } else { printVBEModeInfo(); } } else if ( strcmp( booterCommand, "memory" ) == 0) { if (bootArgs->Video.v_display != VGA_TEXT_MODE ) { showInfoBox("Memory Map", getMemoryInfoString()); } else { printMemoryInfo(); } } else if (strcmp(booterCommand, "lspci") == 0) { lspci(); } else if (strcmp(booterCommand, "more") == 0) { showTextFile(booterParam); } else if (strcmp(booterCommand, "rd") == 0) { processRAMDiskCommand(&argPtr, booterParam); } else if (strcmp(booterCommand, "norescan") == 0) { if (gEnableCDROMRescan) { gEnableCDROMRescan = false; break; } } else { showHelp(); } key = 0; showBootPrompt(nextRow, showPrompt); break; } gBootVolume = menuBVR; setRootVolume(menuBVR); gBIOSDev = menuBVR->biosdev; break; case kEscapeKey: clearBootArgs(); break; case kF5Key: // New behavior: // Clear gBootVolume to restart the loop // if the user enabled rescanning the optical drive. // Otherwise boot the default boot volume. if (gEnableCDROMRescan) { gBootVolume = NULL; clearBootArgs(); } break; case kF10Key: gScanSingleDrive = false; scanDisks(gBIOSDev, &bvCount); gBootVolume = NULL; clearBootArgs(); break; case kTabKey: // New behavior: // Switch between text & graphic interfaces // Only Permitted if started in graphics interface if (useGUI) { if (bootArgs->Video.v_display != VGA_TEXT_MODE) { setVideoMode(VGA_TEXT_MODE, 0); setCursorPosition(0, 0, 0); clearScreenRows(0, kScreenLastRow); // Display banner and show hardware info. printf(bootBanner, (bootInfo->convmem + bootInfo->extmem) / 1024); printf(getVBEInfoString()); clearScreenRows(kMenuTopRow, kMenuTopRow + 2); changeCursor(0, kMenuTopRow, kCursorTypeHidden, 0); nextRow = kMenuTopRow; showPrompt = true; if (gDeviceCount) { printf("Use \30\31 keys to select the startup volume."); showMenu(menuItems, gDeviceCount, selectIndex, kMenuTopRow + 2, kMenuMaxItems); nextRow += MIN(gDeviceCount, kMenuMaxItems) + 3; } showPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot); showBootPrompt(nextRow, showPrompt); //changeCursor( 0, kMenuTopRow, kCursorTypeUnderline, 0 ); } else { gui.redraw = true; setVideoMode(GRAPHICS_MODE, 0); updateVRAM(); updateGraphicBootPrompt(); } } key = 0; break; default: key = 0; break; } } while (0 == key); done: if (bootArgs->Video.v_display == VGA_TEXT_MODE) { clearScreenRows(kMenuTopRow, kScreenLastRow); changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0); } shouldboot = false; gui.menu.draw = false; if (menuItems) { free(menuItems); menuItems = NULL; } if(shouldAddBootUuid) { char tmp[512]; const char* val; int cnt; if(getValueForKey("hajobootuuid", &val, &cnt, &bootInfo->chameleonConfig)) { strncpy(tmp, val, cnt); tmp[cnt] = 0; addBootArg(tmp); } } shouldAddBootUuid = true; return 0; }
void boot(int biosdev) { int status; char *bootFile; unsigned long adler32; BOOL quiet; BOOL firstRun = YES; BVRef bvChain; zeroBSS(); // Initialize malloc malloc_init(0, 0, 0, malloc_error); // Enable A20 gate before accessing memory above 1Mb. enableA20(); // Set reminder to unload the PXE base code. Neglect to unload // the base code will result in a hang or kernel panic. gUnloadPXEOnExit = 1; // Record the device that the booter was loaded from. gBIOSDev = biosdev & kBIOSDevMask; // Initialize boot info structure. initKernBootStruct( gBIOSDev ); // Setup VGA text mode. // Not sure if it is safe to call setVideoMode() before the // config table has been loaded. Call video_mode() instead. video_mode( 2 ); // 80x25 mono text mode. // Scan hardware configuration. scanHardware(); // First get info for boot volume. bvChain = scanBootVolumes(gBIOSDev, 0); // Record default boot device. gBootVolume = selectBootVolume(bvChain); bootArgs->kernDev = MAKEKERNDEV(gBIOSDev, BIOS_DEV_UNIT(gBootVolume), gBootVolume->part_no ); // Load default config file from boot device. status = loadSystemConfig(0, 0); if ( getBoolForKey( kQuietBootKey, &quiet ) && quiet ) { gBootMode |= kBootModeQuiet; } // Parse args, load and start kernel. while (1) { const char *val; int len; int trycache; long flags, cachetime, kerneltime, exttime; int ret = -1; // Initialize globals. sysConfigValid = 0; gErrors = 0; status = getBootOptions(firstRun); firstRun = NO; if (status == -1) continue; status = processBootOptions(); if ( status == 1 ) break; if ( status == -1 ) continue; // Found and loaded a config file. Proceed with boot. // Reset cache name. bzero(gCacheNameAdler, sizeof(gCacheNameAdler)); if ( getValueForKey( kRootDeviceKey, &val, &len ) == YES ) { if (*val == '*') { val++; len--; } strncpy( gCacheNameAdler + 64, val, len ); sprintf(gCacheNameAdler + 64 + len, ",%s", bootArgs->bootFile); } else { strcpy(gCacheNameAdler + 64, bootArgs->bootFile); } adler32 = Adler32(gCacheNameAdler, sizeof(gCacheNameAdler)); if (getValueForKey(kKernelCacheKey, &val, &len) == YES) { strlcpy(gBootKernelCacheFile, val, len+1); } else { sprintf(gBootKernelCacheFile, "%s.%08lX", kDefaultCachePath, adler32); } // Check for cache file. trycache = (((gBootMode & kBootModeSafe) == 0) && (gOverrideKernel == NO) && (gBootFileType == kBlockDeviceType) && (gMKextName[0] == '\0') && (gBootKernelCacheFile[0] != '\0')); printf("Loading Darwin/x86\n"); if (trycache) do { // if we haven't found the kernel yet, don't use the cache ret = GetFileInfo(NULL, bootArgs->bootFile, &flags, &kerneltime); if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)) { trycache = 0; break; } ret = GetFileInfo(NULL, gBootKernelCacheFile, &flags, &cachetime); if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat) || (cachetime < kerneltime)) { trycache = 0; break; } ret = GetFileInfo("/System/Library/", "Extensions", &flags, &exttime); if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory) && (cachetime < exttime)) { trycache = 0; break; } if (kerneltime > exttime) { exttime = kerneltime; } if (cachetime != (exttime + 1)) { trycache = 0; break; } } while (0); do { if (trycache) { bootFile = gBootKernelCacheFile; verbose("Loading kernel cache %s\n", bootFile); ret = LoadFile(bootFile); if (ret >= 0) { break; } } bootFile = bootArgs->bootFile; verbose("Loading kernel %s\n", bootFile); ret = LoadFile(bootFile); } while (0); clearActivityIndicator(); #if DEBUG printf("Pausing..."); sleep(8); #endif if (ret < 0) { error("Can't find %s\n", bootFile); if ( gBootFileType == kBIOSDevTypeFloppy ) { // floppy in drive, but failed to load kernel. gBIOSDev = kBIOSDevTypeHardDrive; initKernBootStruct( gBIOSDev ); printf("Attempting to load from hard drive..."); } else if ( gBootFileType == kNetworkDeviceType ) { // Return control back to PXE. Don't unload PXE base code. gUnloadPXEOnExit = 0; break; } } else { /* Won't return if successful. */ ret = ExecKernel((void *)kLoadAddr); } } /* while(1) */ if ((gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit) { nbpUnloadBaseCode(); } }
int getBootOptions(BOOL firstRun) { int i; int key; int selectIndex = 0; int bvCount; int nextRow; int timeout; BVRef bvr; BVRef bvChain; BVRef menuBVR; BOOL showPrompt, newShowPrompt, isCDROM; MenuItem * menuItems = NULL; if ( diskIsCDROM(gBootVolume) ) isCDROM = TRUE; else isCDROM = FALSE; // Allow user to override default timeout. if ( getIntForKey(kTimeoutKey, &timeout) == NO ) { if ( isCDROM ) timeout = kCDBootTimeout; else timeout = kBootTimeout; } if (timeout < 0) gBootMode |= kBootModeQuiet; // If the user is holding down a modifier key, // enter safe mode. if ( ( readKeyboardShiftFlags() & 0x0F ) != 0 ) { gBootMode |= kBootModeSafe; } // If user typed F8, abort quiet mode, // and display the menu. if (flushKeyboardBuffer()) { gBootMode &= ~kBootModeQuiet; timeout = 0; } clearBootArgs(); setCursorPosition( 0, 0, 0 ); clearScreenRows( 0, kScreenLastRow ); if ( ! ( gBootMode & kBootModeQuiet ) ) { // Display banner and show hardware info. printf( bootBanner, (bootInfo->convmem + bootInfo->extmem) / 1024 ); printVBEInfo(); } changeCursor( 0, kMenuTopRow, kCursorTypeUnderline, 0 ); verbose("Scanning device %x...", gBIOSDev); // Get a list of bootable volumes on the device. bvChain = scanBootVolumes( gBIOSDev, &bvCount ); gBootVolume = menuBVR = selectBootVolume( bvChain ); // When booting from CD, default to hard // drive boot when possible. if ( isCDROM ) { const char *val; char *prompt; int cnt; int optionKey; if (getValueForKey( kCDROMPromptKey, &val, &cnt )) { cnt += 1; prompt = malloc(cnt); strlcpy(prompt, val, cnt); } else { prompt = "Press any key to start up from CD-ROM, " "or press F8 to enter startup options."; cnt = 0; } if (getIntForKey( kCDROMOptionKey, &optionKey )) { // The key specified is a special key. } else if (getValueForKey( kCDROMOptionKey, &val, &cnt) && cnt >= 1) { optionKey = val[0]; } else { // Default to F8. optionKey = 0x4200; } key = countdown(prompt, kMenuTopRow, timeout); if (cnt) free(prompt); clearScreenRows( kMenuTopRow, kMenuTopRow + 2 ); if (key == 0) { // Boot from hard disk. // Scan the original device 0x80. BVRef hd_bvr = selectBootVolume(scanBootVolumes(0x80, 0)); if ( hd_bvr->flags & kBVFlagNativeBoot ) { gBootVolume = hd_bvr; gBIOSDev = hd_bvr->biosdev; initKernBootStruct( gBIOSDev ); goto done; } } else { if (optionKey < 0x100) key = key & 0x5F; if (key != optionKey) goto done; } gBootMode &= ~kBootModeQuiet; timeout = 0; } if ( gBootMode & kBootModeQuiet ) { // No input allowed from user. goto done; } if ( firstRun && ( timeout > 0 ) && ( countdown("Press any key to enter startup options.", kMenuTopRow, timeout) == 0 ) ) { // If the user is holding down a modifier key, // enter safe mode. if ( ( readKeyboardShiftFlags() & 0x0F ) != 0 ) { gBootMode |= kBootModeSafe; } goto done; } if ( bvCount ) { // Allocate memory for an array of menu items. menuItems = (MenuItem *) malloc( sizeof(MenuItem) * bvCount ); if ( menuItems == NULL ) goto done; // Associate a menu item for each BVRef. for ( bvr = bvChain, i = bvCount - 1, selectIndex = 0; bvr; bvr = bvr->next, i-- ) { getBootVolumeDescription( bvr, menuItems[i].name, 80, YES ); menuItems[i].param = (void *) bvr; if ( bvr == menuBVR ) selectIndex = i; } } // Clear screen and hide the blinking cursor. clearScreenRows( kMenuTopRow, kMenuTopRow + 2 ); changeCursor( 0, kMenuTopRow, kCursorTypeHidden, 0 ); nextRow = kMenuTopRow; showPrompt = YES; // Show the menu. if ( bvCount ) { printf("Use \30\31 keys to select the startup volume."); showMenu( menuItems, bvCount, selectIndex, kMenuTopRow + 2, kMenuMaxItems ); nextRow += min( bvCount, kMenuMaxItems ) + 3; } // Show the boot prompt. showPrompt = (bvCount == 0) || (menuBVR->flags & kBVFlagNativeBoot); showBootPrompt( nextRow, showPrompt ); do { key = getc(); updateMenu( key, (void **) &menuBVR ); newShowPrompt = (bvCount == 0) || (menuBVR->flags & kBVFlagNativeBoot); if ( newShowPrompt != showPrompt ) { showPrompt = newShowPrompt; showBootPrompt( nextRow, showPrompt ); } if ( showPrompt ) updateBootArgs( key ); switch ( key & kASCIIKeyMask ) { case kReturnKey: if ( *gBootArgs == '?' ) { if ( strcmp( gBootArgs, "?video" ) == 0 ) { printVBEModeInfo(); } else if ( strcmp( gBootArgs, "?memory" ) == 0 ) { printMemoryInfo(); } else { showHelp(); } key = 0; showBootPrompt( nextRow, showPrompt ); break; } gBootVolume = menuBVR; break; case kEscapeKey: clearBootArgs(); break; default: key = 0; } } while ( 0 == key ); done: firstRun = NO; clearScreenRows( kMenuTopRow, kScreenLastRow ); changeCursor( 0, kMenuTopRow, kCursorTypeUnderline, 0 ); if ( menuItems ) free(menuItems); return 0; }
int processBootOptions() { const char * cp = gBootArgs; const char * val = 0; const char * kernel; int cnt; int userCnt; int cntRemaining; char * argP; char uuidStr[64]; BOOL uuidSet = NO; char * configKernelFlags; char * valueBuffer; valueBuffer = (char *)malloc(VALUE_SIZE); skipblanks( &cp ); // Update the unit and partition number. if ( gBootVolume ) { if ( gBootVolume->flags & kBVFlagForeignBoot ) { readBootSector( gBootVolume->biosdev, gBootVolume->part_boff, (void *) 0x7c00 ); // // Setup edx, and signal intention to chain load the // foreign booter. // chainbootdev = gBootVolume->biosdev; chainbootflag = 1; return 1; } bootInfo->kernDev &= ~((B_UNITMASK << B_UNITSHIFT ) | (B_PARTITIONMASK << B_PARTITIONSHIFT)); bootInfo->kernDev |= MAKEKERNDEV( 0, /* unit */ BIOS_DEV_UNIT(gBootVolume), /* partition */ gBootVolume->part_no ); } // Load config table specified by the user, or use the default. if (getValueForBootKey( cp, "config", &val, &cnt ) == FALSE) { val = 0; cnt = 0; } loadSystemConfig(val, cnt); if ( !sysConfigValid ) return -1; // Use the kernel name specified by the user, or fetch the name // in the config table, or use the default if not specified. // Specifying a kernel name on the command line, or specifying // a non-default kernel name in the config file counts as // overriding the kernel, which causes the kernelcache not // to be used. gOverrideKernel = NO; if (( kernel = extractKernelName((char **)&cp) )) { strcpy( bootInfo->bootFile, kernel ); gOverrideKernel = YES; } else { if ( getValueForKey( kKernelNameKey, &val, &cnt ) ) { strlcpy( bootInfo->bootFile, val, cnt+1 ); if (strcmp( bootInfo->bootFile, kDefaultKernel ) != 0) { gOverrideKernel = YES; } } else { strcpy( bootInfo->bootFile, kDefaultKernel ); } } cntRemaining = BOOT_STRING_LEN - 2; // save 1 for NULL, 1 for space argP = bootArgs->CommandLine; // Get config table kernel flags, if not ignored. if (getValueForBootKey(cp, kIgnoreBootFileFlag, &val, &cnt) == TRUE || getValueForKey( kKernelFlagsKey, &val, &cnt ) == FALSE) { val = ""; cnt = 0; } configKernelFlags = (char *)malloc(cnt + 1); strlcpy(configKernelFlags, val, cnt + 1); if (processBootArgument(kBootUUIDKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, 0)) { // boot-uuid was set either on the command-line // or in the config file. uuidSet = YES; } else { if (GetFSUUID(bootInfo->bootFile, uuidStr) == 0) { verbose("Setting boot-uuid to: %s\n", uuidStr); copyArgument(kBootUUIDKey, uuidStr, strlen(uuidStr), &argP, &cntRemaining); uuidSet = YES; } } if (!processBootArgument(kRootDeviceKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, gRootDevice)) { cnt = 0; if ( getValueForKey( kBootDeviceKey, &val, &cnt)) { valueBuffer[0] = '*'; cnt++; strlcpy(valueBuffer + 1, val, cnt); val = valueBuffer; } else { if (uuidSet) { val = "*uuid"; cnt = 5; } else { // Don't set "rd=.." if there is no boot device key // and no UUID. val = ""; cnt = 0; } } if (cnt > 0) { copyArgument( kRootDeviceKey, val, cnt, &argP, &cntRemaining); } strlcpy( gRootDevice, val, (cnt + 1)); } if (!processBootArgument(kPlatformKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, gPlatformName)) { getPlatformName(gPlatformName); copyArgument(kPlatformKey, gPlatformName, strlen(gPlatformName), &argP, &cntRemaining); } if (!getValueForBootKey(cp, kSafeModeFlag, &val, &cnt) && !getValueForBootKey(configKernelFlags, kSafeModeFlag, &val, &cnt)) { if (gBootMode & kBootModeSafe) { copyArgument(0, kSafeModeFlag, strlen(kSafeModeFlag), &argP, &cntRemaining); } } // Store the merged kernel flags and boot args. cnt = strlen(configKernelFlags); if (cnt) { if (cnt > cntRemaining) { error("Warning: boot arguments too long, truncating\n"); cnt = cntRemaining; } strncpy(argP, configKernelFlags, cnt); argP[cnt++] = ' '; cntRemaining -= cnt; } userCnt = strlen(cp); if (userCnt > cntRemaining) { error("Warning: boot arguments too long, truncating\n"); userCnt = cntRemaining; } strncpy(&argP[cnt], cp, userCnt); argP[cnt+userCnt] = '\0'; gVerboseMode = getValueForKey( kVerboseModeFlag, &val, &cnt ) || getValueForKey( kSingleUserModeFlag, &val, &cnt ); gBootMode = ( getValueForKey( kSafeModeFlag, &val, &cnt ) ) ? kBootModeSafe : kBootModeNormal; if ( getValueForKey( kOldSafeModeFlag, &val, &cnt ) ) { gBootMode = kBootModeSafe; } if ( getValueForKey( kMKextCacheKey, &val, &cnt ) ) { strlcpy(gMKextName, val, cnt + 1); } free(configKernelFlags); free(valueBuffer); return 0; }
void NBI_PreBoot_hook(void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6) { bool dummyVal = 0; config_file_t systemVersion; char valid = false; const char *val; int len; const char* gPrevMacOSBuildVersion; if (!loadConfigFile("System/Library/CoreServices/SystemVersion.plist", &systemVersion)) { valid = true; } else if (!loadConfigFile("System/Library/CoreServices/ServerVersion.plist", &systemVersion)) { valid = true; } if (valid) { if (getValueForKey("ProductBuildVersion", &val, &len, &systemVersion)) { if (!loadConfigFile("Extra/SystemVersion.LastPatched.plist", &systemVersion)) { if(getValueForKey("ProductBuildVersion", &gPrevMacOSBuildVersion, &len, &systemVersion)) { if(strlen(val) != strlen(gPrevMacOSBuildVersion) || strcmp(val, gPrevMacOSBuildVersion) != 0 ) { runNetbookInstaller = 1; } else { // Only allow restore from hibernation if the system hasn't changed, probably a bad idea though //char* val="/private/var/vm/sleepimage"; // Do this first to be sure that root volume is mounted //ret = GetFileInfo(0, val, &flags, &sleeptime); //printf("System version has not changed\n"); //runNetbookInstaller = 0; } } } } } if (!runNetbookInstaller && getBoolForKey("recovery", &dummyVal, DEFAULT_BOOT_CONFIG) && dummyVal) { if(dummyVal) runNetbookInstaller = 2; } if(runNetbookInstaller) { replace_system_function("_LoadDrivers", &NBI_LoadDrivers); if(runNetbookInstaller == 1 ) { if (execute_hook("isRamDiskRegistred", NULL, NULL, NULL, NULL, NULL, NULL) == EFI_SUCCESS) { replace_function_any("_md0Ramdisk", &NBI_md0Ramdisk); } else { register_hook_callback("md0Ramdisk", NBI_md0Ramdisk_hook); } } // Force arch=i386 + -v safe_set_env(envarchCpuType, CPU_TYPE_I386); safe_set_env(envgVerboseMode, true); } }
// Notify OS X that a ramdisk has been setup. XNU will attach this to /dev/md0 void md0Ramdisk() { RAMDiskParam ramdiskPtr; char filename[512]; const char* override_filename = 0; int fh = -1; int len; if (getValueForKey(kMD0ImageKey, &override_filename, &len, &bootInfo->bootConfig)) { // Use user specified md0 file sprintf(filename, "%s", override_filename); fh = open(filename, 0); if (fh < 0) { sprintf(filename, "rd(0,0)/Extra/Postboot.img"); fh = open(filename, 0); if (fh < 0) { sprintf(filename, "bt(0,0)/Extra/Postboot.img"); // Check /Extra if not in rd(0,0) fh = open(filename, 0); } } } if (fh >= 0) { verbose("Enabling ramdisk %s\n", filename); ramdiskPtr.size = file_size(fh); ramdiskPtr.base = AllocateKernelMemory(ramdiskPtr.size); if (ramdiskPtr.size && ramdiskPtr.base) { // Read new ramdisk image contents in kernel memory. if (read(fh, (char*) ramdiskPtr.base, ramdiskPtr.size) == ramdiskPtr.size) { AllocateMemoryRange("RAMDisk", ramdiskPtr.base, ramdiskPtr.size, kBootDriverTypeInvalid); Node* node = DT__FindNode("/chosen/memory-map", false); if (node != NULL) { DT__AddProperty(node, "RAMDisk", sizeof(RAMDiskParam), (void*)&ramdiskPtr); } else { verbose("Unable to notify Mac OS X of the ramdisk %s.\n", filename); } } else { verbose("Unable to read md0 image %s.\n", filename); } } else { verbose("md0 image %s is empty.\n", filename); } close(fh); } }
int processBootOptions() { const char * cp = gBootArgs; const char * val = 0; const char * kernel; int cnt; int userCnt; int cntRemaining; char * argP; skipblanks( &cp ); // Update the unit and partition number. if ( gBootVolume ) { if ( gBootVolume->flags & kBVFlagForeignBoot ) { readBootSector( gBootVolume->biosdev, gBootVolume->part_boff, (void *) 0x7c00 ); // // Setup edx, and signal intention to chain load the // foreign booter. // chainbootdev = gBootVolume->biosdev; chainbootflag = 1; return 1; } bootArgs->kernDev &= ~((B_UNITMASK << B_UNITSHIFT ) | (B_PARTITIONMASK << B_PARTITIONSHIFT)); bootArgs->kernDev |= MAKEKERNDEV( 0, /* unit */ BIOS_DEV_UNIT(gBootVolume), /* partition */ gBootVolume->part_no ); } // Load config table specified by the user, or use the default. if (getValueForBootKey( cp, "config", &val, &cnt ) == FALSE) { val = 0; cnt = 0; } loadSystemConfig(val, cnt); if ( !sysConfigValid ) return -1; // Use the kernel name specified by the user, or fetch the name // in the config table, or use the default if not specified. // Specifying a kernel name on the command line, or specifying // a non-default kernel name in the config file counts as // overriding the kernel, which causes the kernelcache not // to be used. gOverrideKernel = NO; if (( kernel = extractKernelName((char **)&cp) )) { strcpy( bootArgs->bootFile, kernel ); gOverrideKernel = YES; } else { if ( getValueForKey( kKernelNameKey, &val, &cnt ) ) { strlcpy( bootArgs->bootFile, val, cnt+1 ); if (strcmp( bootArgs->bootFile, kDefaultKernel ) != 0) { gOverrideKernel = YES; } } else { strcpy( bootArgs->bootFile, kDefaultKernel ); } } cntRemaining = BOOT_STRING_LEN - 2; // save 1 for NULL, 1 for space // Check to see if we need to specify root device. // If user types "rd=.." on the boot line, it overrides // the boot device key in the boot arguments file. // argP = bootArgs->bootString; if ( getValueForBootKey( cp, kRootDeviceKey, &val, &cnt ) == FALSE && getValueForKey( kRootDeviceKey, &val, &cnt ) == FALSE ) { if ( getValueForKey( kBootDeviceKey, &val, &cnt ) ) { strcpy( argP, "rd=*" ); argP += 4; strlcpy( argP, val, cnt+1); cntRemaining -= cnt; argP += cnt; *argP++ = ' '; } } // Check to see if we should ignore saved kernel flags. if (getValueForBootKey(cp, kIgnoreBootFileFlag, &val, &cnt) == FALSE) { if (getValueForKey( kKernelFlagsKey, &val, &cnt ) == FALSE) { val = 0; cnt = 0; } } // Store the merged kernel flags and boot args. if (cnt > cntRemaining) { error("Warning: boot arguments too long, truncated\n"); cnt = cntRemaining; } if (cnt) { strncpy(argP, val, cnt); argP[cnt++] = ' '; } cntRemaining = cntRemaining - cnt; userCnt = strlen(cp); if (userCnt > cntRemaining) { error("Warning: boot arguments too long, truncated\n"); userCnt = cntRemaining; } strncpy(&argP[cnt], cp, userCnt); argP[cnt+userCnt] = '\0'; gVerboseMode = getValueForKey( kVerboseModeFlag, &val, &cnt ) || getValueForKey( kSingleUserModeFlag, &val, &cnt ); gBootMode = ( getValueForKey( kSafeModeFlag, &val, &cnt ) ) ? kBootModeSafe : kBootModeNormal; if ( getValueForKey( kPlatformKey, &val, &cnt ) ) { strlcpy(gPlatformName, val, cnt + 1); } else { strcpy(gPlatformName, "ACPI"); } if ( getValueForKey( kMKextCacheKey, &val, &cnt ) ) { strlcpy(gMKextName, val, cnt + 1); } return 0; }
//========================================================================== // The 'main' function for the booter. Called by boot0 when booting // from a block device, or by the network booter. // // arguments: // biosdev - Value passed from boot1/NBP to specify the device // that the booter was loaded from. // // If biosdev is kBIOSDevNetwork, then this function will return if // booting was unsuccessful. This allows the PXE firmware to try the // next boot device on its list. void common_boot(int biosdev) { const char *val; char *bootFile; unsigned long adler32; int status; int cnt; bool quiet; bool firstRun = true; bool instantMenu; bool rescanPrompt; // Record the device that the booter was loaded from. gBIOSDev = biosdev & kBIOSDevMask; // Initialize boot info structure. initKernBootStruct(); // Setup VGA text mode. // Not sure if it is safe to call setVideoMode() before the // config table has been loaded. Call video_mode() instead. #if DEBUG printf("before video_mode\n"); #endif video_mode( 2 ); // 80x25 mono text mode. #if DEBUG printf("after video_mode\n"); #endif // First get info for boot volume. scanBootVolumes(gBIOSDev, 0); bvChain = getBVChainForBIOSDev(gBIOSDev); setBootGlobals(bvChain); // Load boot.plist config file status = loadSystemConfig(&bootInfo->bootConfig); if (getBoolForKey(kQuietBootKey, &quiet, &bootInfo->bootConfig) && quiet) { gBootMode |= kBootModeQuiet; } // Get verbosity at early stage to allow a quiet booter if (getValueForKey(kKernelFlagsKey, &val, &cnt, &bootInfo->bootConfig)) { if (getValueForBootKey(val, kVerboseModeFlag, &val, &cnt)) { gVerboseMode = true; } } // Scan and record the system's hardware information. scan_platform(); // Override firstRun to get to the boot menu instantly by setting "Instant Menu"=y in system config if (getBoolForKey(kInsantMenuKey, &instantMenu, &bootInfo->bootConfig) && instantMenu) { firstRun = false; } // Loading preboot ramdisk if exists. loadPrebootRAMDisk(); // Disable rescan option by default gEnableCDROMRescan = false; // Enable it with Rescan=y in system config if (getBoolForKey(kRescanKey, &gEnableCDROMRescan, &bootInfo->bootConfig) && gEnableCDROMRescan) { gEnableCDROMRescan = true; } // Ask the user for Rescan option by setting "Rescan Prompt"=y in system config. rescanPrompt = false; if (getBoolForKey(kRescanPromptKey, &rescanPrompt , &bootInfo->bootConfig) && rescanPrompt && biosDevIsCDROM(gBIOSDev)) { gEnableCDROMRescan = promptForRescanOption(); } // Enable touching a single BIOS device only if "Scan Single Drive"=y is set in system config. if (getBoolForKey(kScanSingleDriveKey, &gScanSingleDrive, &bootInfo->bootConfig) && gScanSingleDrive) { gScanSingleDrive = true; } // Create a list of partitions on device(s). if (gScanSingleDrive) { scanBootVolumes(gBIOSDev, &bvCount); } else { scanDisks(gBIOSDev, &bvCount); } // Create a separated bvr chain using the specified filters. bvChain = newFilteredBVChain(0x80, 0xFF, kBVFlagSystemVolume|kBVFlagForeignBoot, kBVFlagEFISystem, &gDeviceCount); gBootVolume = selectBootVolume(bvChain); #if DEBUG printf(" Default: %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBootVolume, gBootVolume->biosdev, gBootVolume->part_no, gBootVolume->flags); printf(" bt(0,0): %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBIOSBootVolume, gBIOSBootVolume->biosdev, gBIOSBootVolume->part_no, gBIOSBootVolume->flags); getc(); #endif useGUI = true; // Override useGUI default getBoolForKey(kGUIKey, &useGUI, &bootInfo->bootConfig); if (useGUI) { if (gVerboseMode) { printf("Switching to GUI mode in 3 seconds...\n"); sleep(3); } initGUI(); /* XXX AsereBLN handle error */ } setBootGlobals(bvChain); // Parse args, load and start kernel. while (1) { const char *val; int len; int trycache; long flags, cachetime, kerneltime, exttime, sleeptime, time; int ret = -1; void *binary = (void *)kLoadAddr; bool tryresume; bool tryresumedefault; bool forceresume; config_file_t systemVersion; // system.plist of booting partition // additional variable for testing alternate kernel image locations on boot helper partitions. char bootFileSpec[512]; // Initialize globals. sysConfigValid = false; gErrors = false; getBootOptions(firstRun); firstRun = false; status = processBootOptions(); // Status==1 means to chainboot if ( status == 1 ) break; // Status==-1 means that the config file couldn't be loaded or that gBootVolume is NULL if ( status == -1 ) { // gBootVolume == NULL usually means the user hit escape. if(gBootVolume == NULL) { freeFilteredBVChain(bvChain); if (gEnableCDROMRescan) rescanBIOSDevice(gBIOSDev); bvChain = newFilteredBVChain(0x80, 0xFF, kBVFlagSystemVolume|kBVFlagForeignBoot, kBVFlagEFISystem, &gDeviceCount); setBootGlobals(bvChain); } continue; } // Other status (e.g. 0) means that we should proceed with boot. if( bootArgs->Video.v_display == GRAPHICS_MODE ) drawBackground(); // Found and loaded a config file. Proceed with boot. // Turn off any GUI elements if( bootArgs->Video.v_display == GRAPHICS_MODE ) { gui.devicelist.draw = false; gui.bootprompt.draw = false; gui.menu.draw = false; gui.infobox.draw = false; drawBackground(); updateVRAM(); } // Find out which version mac os we're booting. if (!loadConfigFile("System/Library/CoreServices/SystemVersion.plist", &systemVersion)) { if (getValueForKey(kProductVersion, &val, &len, &systemVersion)) { // getValueForKey uses const char for val // so copy it and trim strncpy(gMacOSVersion, val, MIN(len, 4)); gMacOSVersion[MIN(len, 4)] = '\0'; } } if (platformCPUFeature(CPU_FEATURE_EM64T)) { archCpuType = CPU_TYPE_X86_64; } else { archCpuType = CPU_TYPE_I386; } if (getValueForKey(karch, &val, &len, &bootInfo->bootConfig)) { if (strncmp(val, "i386", 4) == 0) { archCpuType = CPU_TYPE_I386; } } if (getValueForKey(k32BitModeFlag, &val, &len, &bootInfo->bootConfig)) { archCpuType = CPU_TYPE_I386; } if (!getBoolForKey (kWake, &tryresume, &bootInfo->bootConfig)) { tryresume = true; tryresumedefault = true; } else { tryresumedefault = false; } if (!getBoolForKey (kForceWake, &forceresume, &bootInfo->bootConfig)) { forceresume = false; } if (forceresume) { tryresume = true; tryresumedefault = false; } while (tryresume) { const char *tmp; BVRef bvr; if (!getValueForKey(kWakeImage, &val, &len, &bootInfo->bootConfig)) val="/private/var/vm/sleepimage"; // Do this first to be sure that root volume is mounted ret = GetFileInfo(0, val, &flags, &sleeptime); if ((bvr = getBootVolumeRef(val, &tmp)) == NULL) break; // Can't check if it was hibernation Wake=y is required if (bvr->modTime == 0 && tryresumedefault) break; if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)) break; if (!forceresume && sleeptime+3<bvr->modTime) { printf ("Hibernate image is too old by %d seconds. Use ForceWake=y to override\n",bvr->modTime-sleeptime); break; } HibernateBoot((char *)val); break; } // Reset cache name. bzero(gCacheNameAdler + 64, sizeof(gCacheNameAdler) - 64); sprintf(gCacheNameAdler + 64, "%s,%s", gRootDevice, bootInfo->bootFile); adler32 = Adler32((unsigned char *)gCacheNameAdler, sizeof(gCacheNameAdler)); if (getValueForKey(kKernelCacheKey, &val, &len, &bootInfo->bootConfig)) { strlcpy(gBootKernelCacheFile, val, len+1); } else { sprintf(gBootKernelCacheFile, "%s.%08lX", kDefaultCachePath, adler32); } // Check for cache file. trycache = (((gBootMode & kBootModeSafe) == 0) && !gOverrideKernel && (gMKextName[0] == '\0') && (gBootKernelCacheFile[0] != '\0')); verbose("Loading Darwin %s\n", gMacOSVersion); if (trycache) do { // if we haven't found the kernel yet, don't use the cache ret = GetFileInfo(NULL, bootInfo->bootFile, &flags, &kerneltime); if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)) { trycache = 0; break; } ret = GetFileInfo(NULL, gBootKernelCacheFile, &flags, &cachetime); if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat) || (cachetime < kerneltime)) { trycache = 0; break; } ret = GetFileInfo("/System/Library/", "Extensions", &flags, &exttime); if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory) && (cachetime < exttime)) { trycache = 0; break; } if (kerneltime > exttime) { exttime = kerneltime; } if (cachetime != (exttime + 1)) { trycache = 0; break; } } while (0); do { if (trycache) { bootFile = gBootKernelCacheFile; verbose("Loading kernel cache %s\n", bootFile); ret = LoadFile(bootFile); binary = (void *)kLoadAddr; if (ret >= 0) { break; } } bootFile = bootInfo->bootFile; // Try to load kernel image from alternate locations on boot helper partitions. sprintf(bootFileSpec, "com.apple.boot.P/%s", bootFile); ret = GetFileInfo(NULL, bootFileSpec, &flags, &time); if (ret == -1) { sprintf(bootFileSpec, "com.apple.boot.R/%s", bootFile); ret = GetFileInfo(NULL, bootFileSpec, &flags, &time); if (ret == -1) { sprintf(bootFileSpec, "com.apple.boot.S/%s", bootFile); ret = GetFileInfo(NULL, bootFileSpec, &flags, &time); if (ret == -1) { // Not found any alternate locations, using the original kernel image path. strcpy(bootFileSpec, bootFile); } } } verbose("Loading kernel %s\n", bootFileSpec); ret = LoadThinFatFile(bootFileSpec, &binary); if (ret <= 0 && archCpuType == CPU_TYPE_X86_64) { archCpuType = CPU_TYPE_I386; ret = LoadThinFatFile(bootFileSpec, &binary); } } while (0); clearActivityIndicator(); #if DEBUG printf("Pausing..."); sleep(8); #endif if (ret <= 0) { printf("Can't find %s\n", bootFile); if(gui.initialised) { sleep(1); drawBackground(); gui.devicelist.draw = true; gui.redraw = true; } } else { /* Won't return if successful. */ ret = ExecKernel(binary); } } // chainboot if (status==1) { if (getVideoMode() == GRAPHICS_MODE) { // if we are already in graphics-mode, setVideoMode(VGA_TEXT_MODE, 0); // switch back to text mode } } }
void Scene::initialize( const std::vector<ActorUId>& persistent_actors ) { mSceneManager = EventManager::create("Scene "+mName+" Manager"); Controller::get()->eventManager()->addListener(fastdelegate::MakeDelegate(this, &Scene::handleInitGUI), InitGUIEvent::TYPE); Controller::get()->eventManager()->addListener( fastdelegate::MakeDelegate(this, &Scene::handleSceneUpdate), SceneUpdateEvent::TYPE ); Controller::get()->eventManager()->addListener( fastdelegate::MakeDelegate(this, &Scene::handleReturnActorCreate), ReturnActorCreatedEvent::TYPE ); Controller::get()->eventManager()->addListener( fastdelegate::MakeDelegate(this, &Scene::handleScenePreDraw), ScenePreDrawEvent::TYPE ); Controller::get()->eventManager()->addListener( fastdelegate::MakeDelegate(this, &Scene::handleSceneDraw), SceneDrawEvent::TYPE ); Controller::get()->eventManager()->addListener( fastdelegate::MakeDelegate(this, &Scene::handleShutDown), ShutDownEvent::TYPE ); if( !persistent_actors.empty() ){ for(auto &id : persistent_actors) { auto actor_weak = ActorManager::get()->retreiveUnique(id); mActors.insert( std::make_pair(id, actor_weak) ); } } auto init = ConfigManager::get()->retreiveActorsForScene( mName ); ///call to inherited initialize for sub classes to pulll custom shit out of the config initialize( ConfigManager::get()->retreiveScene(mName) ); try { //TODO: the problem with persistent actors is how to manage state across scenes, how to identify actors of the same type across scenes that are persistent, one solution is destroy all and reload referencing a serialized state file that is written out and read back in or something //for now, just sending across actors marked 'persistent' and not including them in the config for the next scene, the state has to be handled at runtime then auto & actors = init.getChildren(); auto it = actors.begin(); auto end = actors.end(); for(;it!=end;++it){ auto actor_name = it->getValueForKey("name"); CI_LOG_V("found actor: "+actor_name); auto onInit = it->getValueForKey<bool>( "create_on_scene_init" ); auto persistent = it->getValueForKey<bool>( "persistent" ); if( persistent ){ //make sure its not already in there if( !ec::ActorManager::get()->actorExists( ec::getHash(actor_name) ) ){ if( onInit ){ //make sure it shuld be created on scene init CI_LOG_V("creating actor: "+actor_name); Controller::get()->eventManager()->triggerEvent( CreateActorEvent::create( mName, actor_name) ); } } }else if (onInit){ //make sure it shuld be created on scene init CI_LOG_V("creating actor: "+actor_name); Controller::get()->eventManager()->triggerEvent( CreateActorEvent::create( mName, actor_name) ); } } } catch (const ci::JsonTree::ExcChildNotFound &e) { CI_LOG_E("actors not found in init"); } ///POST INITIALIZE ALL ACTORS auto actor = mActors.begin(); auto end = mActors.end(); while( actor != end ) { if(auto a = (*actor).second.lock()){ a->postInit(); ++actor; }else{ CI_LOG_E("Actor is missing"); ec::Controller::get()->eventManager()->triggerEvent(DestoryActorEvent::create((*actor).first)); actor = mActors.erase(actor); } } postInit(); ///run setup events; manager()->update(); }
bool setup_gma_devprop(pci_dt_t *gma_dev) { char *devicepath = NULL; volatile uint8_t *regs; uint32_t bar[7]; char *model = NULL; uint8_t BuiltIn = 0x00; uint16_t vendor_id = gma_dev->vendor_id; uint16_t device_id = gma_dev->device_id; uint8_t ClassFix[4] = { 0x00, 0x00, 0x03, 0x00 }; int n_igs = 0; int len; const char *value; devicepath = get_pci_dev_path(gma_dev); bar[0] = pci_config_read32(gma_dev->dev.addr, 0x10); regs = (uint8_t *) (bar[0] & ~0x0f); model = get_gma_controller_name(device_id, vendor_id); verbose("---------------------------------------------\n"); verbose("------------ INTEL DEVICE INFO --------------\n"); verbose("---------------------------------------------\n"); verbose("Class code: [%04x]\n%s [%04x:%04x] (rev %02x)\nSubsystem: [%04x:%04x] :: %s\n", gma_dev->class_id, model, gma_dev->vendor_id, gma_dev->device_id, gma_dev->revision_id, gma_dev->subsys_id.subsys.vendor_id, gma_dev->subsys_id.subsys.device_id, devicepath); if (!string) { string = devprop_create_string(); } struct DevPropDevice *device = devprop_add_device(string, devicepath); if (!device) { printf("Failed initializing dev-prop string dev-entry.\n"); pause(); return false; } devprop_add_value(device, "model", (uint8_t*)model, (strlen(model) + 1)); devprop_add_value(device, "device_type", (uint8_t*)"display", 8); switch ((device_id << 16) | vendor_id) { case GMA_IRONLAKE_D_G: // 0042 case GMA_IRONLAKE_M_G: // 0046 devprop_add_value(device, "built-in", &BuiltIn, 1); devprop_add_value(device, "class-code", ClassFix, 4); devprop_add_value(device, "hda-gfx", (uint8_t *)"onboard-1", 10); devprop_add_value(device, "AAPL,os-info", HDx000_os_info, 20); break; /* 27A2, 27AE, 27A6, A001, A011, A012, */ case GMA_I945_GM: // Mobile GMA950 Mobile GMA3150 case GMA_I945_GME: //case GMA_945GM: case GMA_PINEVIEW_G: case GMA_PINEVIEW_M: case GMA_GMA3150_M: devprop_add_value(device, "AAPL,HasPanel", reg_TRUE, 4); devprop_add_value(device, "built-in", &BuiltIn, 1); devprop_add_value(device, "class-code", ClassFix, 4); break; /* 2772 ,2776, A002 */ case GMA_I945_G: // Desktop GMA950 Desktop GMA3150 //case GMA_82945G: case GMA_GMA3150_D: BuiltIn = 0x01; devprop_add_value(device, "built-in", &BuiltIn, 1); devprop_add_value(device, "class-code", ClassFix, 4); break; /* 2A02, 2A12, 2A13, 2A42, 2A43 */ case GMA_I965_GM: // GMAX3100 case GMA_I965_GME: //case 0x80862A13: case GMA_GM45_GM: //case GMA_GM45_GM2: devprop_add_value(device, "AAPL,HasPanel", GMAX3100_vals[0], 4); devprop_add_value(device, "AAPL,SelfRefreshSupported", GMAX3100_vals[1], 4); devprop_add_value(device, "AAPL,aux-power-connected", GMAX3100_vals[2], 4); devprop_add_value(device, "AAPL,backlight-control", GMAX3100_vals[3], 4); devprop_add_value(device, "AAPL00,blackscreen-preferences", GMAX3100_vals[4], 4); devprop_add_value(device, "AAPL01,BacklightIntensity", GMAX3100_vals[5], 4); devprop_add_value(device, "AAPL01,blackscreen-preferences", GMAX3100_vals[6], 4); devprop_add_value(device, "AAPL01,DataJustify", GMAX3100_vals[7], 4); devprop_add_value(device, "AAPL01,Depth", GMAX3100_vals[8], 4); devprop_add_value(device, "AAPL01,Dither", GMAX3100_vals[9], 4); devprop_add_value(device, "AAPL01,DualLink", GMAX3100_vals[10], 4); devprop_add_value(device, "AAPL01,Height", GMAX3100_vals[11], 4); devprop_add_value(device, "AAPL01,Interlace", GMAX3100_vals[12], 4); devprop_add_value(device, "AAPL01,Inverter", GMAX3100_vals[13], 4); devprop_add_value(device, "AAPL01,InverterCurrent", GMAX3100_vals[14], 4); devprop_add_value(device, "AAPL01,InverterCurrency", GMAX3100_vals[15], 4); devprop_add_value(device, "AAPL01,LinkFormat", GMAX3100_vals[16], 4); devprop_add_value(device, "AAPL01,LinkType", GMAX3100_vals[17], 4); devprop_add_value(device, "AAPL01,Pipe", GMAX3100_vals[18], 4); devprop_add_value(device, "AAPL01,PixelFormat", GMAX3100_vals[19], 4); devprop_add_value(device, "AAPL01,Refresh", GMAX3100_vals[20], 4); devprop_add_value(device, "AAPL01,Stretch", GMAX3100_vals[21], 4); //devprop_add_value(device, "AAPL01,InverterFrequency", GMAX3100_vals[22], 4); devprop_add_value(device, "class-code", ClassFix, 4); break; /* 0106 */ case GMA_SANDYBRIDGE_M_GT1: // HD Graphics 2000 Mobile devprop_add_value(device, "class-code", ClassFix, 4); devprop_add_value(device, "hda-gfx", (uint8_t *)"onboard-1", 10); devprop_add_value(device, "AAPL00,PixelFormat", HD2000_vals[0], 4); devprop_add_value(device, "AAPL00,T1", HD2000_vals[1], 4); devprop_add_value(device, "AAPL00,T2", HD2000_vals[2], 4); devprop_add_value(device, "AAPL00,T3", HD2000_vals[3], 4); devprop_add_value(device, "AAPL00,T4", HD2000_vals[4], 4); devprop_add_value(device, "AAPL00,T5", HD2000_vals[5], 4); devprop_add_value(device, "AAPL00,T6", HD2000_vals[6], 4); devprop_add_value(device, "AAPL00,T7", HD2000_vals[7], 4); devprop_add_value(device, "AAPL00,LinkType", HD2000_vals[8], 4); devprop_add_value(device, "AAPL00,LinkFormat", HD2000_vals[9], 4); devprop_add_value(device, "AAPL00,DualLink", HD2000_vals[10], 4); devprop_add_value(device, "AAPL00,Dither", HD2000_vals[11], 4); devprop_add_value(device, "AAPL00,DataJustify", HD3000_vals[12], 4); devprop_add_value(device, "graphic-options", HD2000_vals[13], 4); devprop_add_value(device, "AAPL,tbl-info", HD2000_tbl_info, 18); devprop_add_value(device, "AAPL,os-info", HD2000_os_info, 20); break; /* 0116, 0126 */ case GMA_SANDYBRIDGE_M_GT2: // HD Graphics 3000 Mobile case GMA_SANDYBRIDGE_M_GT2_PLUS: devprop_add_value(device, "class-code", ClassFix, 4); devprop_add_value(device, "hda-gfx", (uint8_t *)"onboard-1", 10); devprop_add_value(device, "AAPL00,PixelFormat", HD3000_vals[0], 4); devprop_add_value(device, "AAPL00,T1", HD3000_vals[1], 4); devprop_add_value(device, "AAPL00,T2", HD3000_vals[2], 4); devprop_add_value(device, "AAPL00,T3", HD3000_vals[3], 4); devprop_add_value(device, "AAPL00,T4", HD3000_vals[4], 4); devprop_add_value(device, "AAPL00,T5", HD3000_vals[5], 4); devprop_add_value(device, "AAPL00,T6", HD3000_vals[6], 4); devprop_add_value(device, "AAPL00,T7", HD3000_vals[7], 4); devprop_add_value(device, "AAPL00,LinkType", HD3000_vals[8], 4); devprop_add_value(device, "AAPL00,LinkFormat", HD3000_vals[9], 4); devprop_add_value(device, "AAPL00,DualLink", HD3000_vals[10], 4); devprop_add_value(device, "AAPL00,Dither", HD3000_vals[11], 4); devprop_add_value(device, "AAPL00,DataJustify", HD3000_vals[12], 4); devprop_add_value(device, "graphic-options", HD3000_vals[13], 4); devprop_add_value(device, "AAPL,tbl-info", HD3000_tbl_info, 18); devprop_add_value(device, "AAPL,os-info", HD3000_os_info, 20); devprop_add_value(device, "AAPL,snb-platform-id", HD3000_vals[16], 4);// previusly commented break; /* 0102 */ /* HD Graphics 2000 */ case GMA_SANDYBRIDGE_GT1: // 0102 device_id = 0x00000102; // Inject a valid mobile GPU device id instead of patching kexts devprop_add_value(device, "built-in", &BuiltIn, 1); devprop_add_value(device, "class-code", ClassFix, 4); devprop_add_value(device, "device-id", (uint8_t*)&device_id, sizeof(device_id)); devprop_add_value(device, "hda-gfx", (uint8_t *)"onboard-1", 10); devprop_add_value(device, "AAPL,tbl-info", HD2000_tbl_info, 18); devprop_add_value(device, "AAPL,os-info", HD2000_os_info, 20); break; /* Sandy Bridge */ /* HD Graphics 3000 */ case GMA_SANDYBRIDGE_GT2: // 0112 case GMA_SANDYBRIDGE_GT2_PLUS: // 0122 devprop_add_value(device, "built-in", &BuiltIn, 1); devprop_add_value(device, "class-code", ClassFix, 4); device_id = 0x00000126; // Inject a valid mobile GPU device id instead of patching kexts devprop_add_value(device, "device-id", (uint8_t*)&device_id, sizeof(device_id)); devprop_add_value(device, "hda-gfx", (uint8_t *)"onboard-1", 10); devprop_add_value(device, "AAPL,tbl-info", HD3000_tbl_info, 18); devprop_add_value(device, "AAPL,os-info", HD3000_os_info, 20); break; /* Ivy Bridge */ /* HD Graphics 4000, HD Graphics 4000 Mobile, HD Graphics P4000, HD Graphics 2500 HD, Graphics 2500 Mobile */ case GMA_IVYBRIDGE_D_GT1: // 0152 case GMA_IVYBRIDGE_M_GT1: // 0156 case GMA_IVYBRIDGE_S_GT1: // 015A case GMA_IVYBRIDGE_S_GT3: // 015e case GMA_IVYBRIDGE_D_GT2: // 0162 case GMA_IVYBRIDGE_M_GT2: // 0166 case GMA_IVYBRIDGE_S_GT2: // 016A case GMA_IVYBRIDGE_S_GT4: // 0172 case GMA_IVYBRIDGE_S_GT5: // 0176 if (getValueForKey(kAAPLCustomIG, &value, &len, &bootInfo->chameleonConfig) && len == AAPL_LEN_IVY * 2) { uint8_t new_aapl0[AAPL_LEN_IVY]; if (hex2bin(value, new_aapl0, AAPL_LEN_IVY) == 0) { memcpy(default_aapl_ivy, new_aapl0, AAPL_LEN_IVY); verbose("Using user supplied AAPL,ig-platform-id\n"); verbose("AAPL,ig-platform-id: %02x%02x%02x%02x\n", default_aapl_ivy[0], default_aapl_ivy[1], default_aapl_ivy[2], default_aapl_ivy[3]); } devprop_add_value(device, "AAPL,ig-platform-id", default_aapl_ivy, AAPL_LEN_IVY); } else if (getIntForKey(kIntelCapriFB, &n_igs, &bootInfo->chameleonConfig)) { if ((n_igs >= 0) || (n_igs <= 11)) { verbose("AAPL,ig-platform-id was set in org.chameleon.Boot.plist with value %d\n", n_igs); devprop_add_value(device, "AAPL,ig-platform-id", ivy_bridge_ig_vals[n_igs], 4); } else { verbose("AAPL,ig-platform-id was set in org.chameleon.Boot.plist with bad value please choose a number between 0 and 11.\n"); } } else { uint32_t ig_platform_id; uint32_t ram = (((getVBEVideoRam() + 512) / 1024) + 512) / 1024; switch (ram) { case 96: ig_platform_id = 0x01660000; // 96mb Mobile break; case 64: ig_platform_id = 0x01660009; // 64mb Mobile break; case 32: ig_platform_id = 0x01620005; // 32mb Desktop break; default: printf("Please specify 96, 64, or 32MB RAM for the HD4000 in the bios.\n" "The selected %dMB RAM configuration is not supported for the HD4000.\n", ram); pause(); return false; // Exit early before the AAPL,ig-platform-id property is set. break; } devprop_add_value(device, "AAPL,ig-platform-id", (uint8_t *)&ig_platform_id, 4); } devprop_add_value(device, "AAPL00,DualLink", HD4000_vals[10], 4); devprop_add_value(device, "built-in", &BuiltIn, 1); devprop_add_value(device, "class-code", ClassFix, 4); devprop_add_value(device, "hda-gfx", (uint8_t *)"onboard-1", 10); break; /* Haswell */ /* HD Graphics 5000, HD Graphics 5000 Mobile, HD Graphics P5000, HD Graphics 4600, HD Graphics 4600 Mobile */ //case 0x80860090: //case 0x80860091: //case 0x80860092: case GMA_HASWELL_D_GT1: // 0402 case GMA_HASWELL_M_GT1: // 0406 case GMA_HASWELL_S_GT1: // 040a case GMA_HASWELL_D_GT2: // 0412 case GMA_HASWELL_M_GT2: // 0416 case GMA_HASWELL_S_GT2: // 041a case GMA_HASWELL_E_GT1: // 040e case GMA_HASWELL_E_GT2: // 041e case GMA_HASWELL_E_GT3: // 042e case GMA_HASWELL_D_GT3: // 0422 case GMA_HASWELL_M_GT3: // 0426 case GMA_HASWELL_S_GT3: // 042a case GMA_HASWELL_ULT_M_GT1: // 0a06 case GMA_HASWELL_ULT_E_GT1: // 0a0e case GMA_HASWELL_ULT_M_GT2: // 0a16 case GMA_HASWELL_ULT_E_GT2: // 0a1e case GMA_HASWELL_ULT_D_GT3: // 0a22 case GMA_HASWELL_ULT_M_GT3: // 0a26 case GMA_HASWELL_ULT_S_GT3: // 0a2a case GMA_HASWELL_ULT_E_GT3: // 0a2e case GMA_HASWELL_SDV_D_GT1_IG: // 0c02 case GMA_HASWELL_SDV_M_GT1_IG: // 0c06 case GMA_HASWELL_SDV_D_GT2_IG: // 0c12 case GMA_HASWELL_SDV_M_GT2_IG: // 0c16 case GMA_HASWELL_SDV_D_GT2_PLUS_IG: // 0c22 case GMA_HASWELL_SDV_M_GT2_PLUS_IG: // 0c26 case GMA_HASWELL_CRW_D_GT1: // 0d02 case GMA_HASWELL_CRW_D_GT2: // 0d12 case GMA_HASWELL_CRW_D_GT3: // 0d22 case GMA_HASWELL_CRW_M_GT1: // 0d06 case GMA_HASWELL_CRW_M_GT2: // 0d16 case GMA_HASWELL_CRW_M_GT3: // 0d26 case GMA_HASWELL_CRW_S_GT1: // 0d0a case GMA_HASWELL_CRW_S_GT2: // 0d1a case GMA_HASWELL_CRW_S_GT3: // 0d2a case GMA_HASWELL_CRW_B_GT1: // 0d0b case GMA_HASWELL_CRW_B_GT2: // 0d1b case GMA_HASWELL_CRW_B_GT3: // 0d2b case GMA_HASWELL_CRW_E_GT1: // 0d0e case GMA_HASWELL_CRW_E_GT2: // 0d1e case GMA_HASWELL_CRW_E_GT3: // 0d2e case GMA_HASWELL_CRW_M_GT2_PLUS_IG: // 0d36 if (getValueForKey(kAAPLCustomIG, &value, &len, &bootInfo->chameleonConfig) && len == AAPL_LEN_HSW * 2) { uint8_t new_aapl0[AAPL_LEN_HSW]; if (hex2bin(value, new_aapl0, AAPL_LEN_HSW) == 0) { memcpy(default_aapl_haswell, new_aapl0, AAPL_LEN_HSW); verbose("Using user supplied AAPL,ig-platform-id\n"); verbose("AAPL,ig-platform-id: %02x%02x%02x%02x\n", default_aapl_haswell[0], default_aapl_haswell[1], default_aapl_haswell[2], default_aapl_haswell[3]); } devprop_add_value(device, "AAPL,ig-platform-id", default_aapl_haswell, AAPL_LEN_HSW); } else if (getIntForKey(kIntelAzulFB, &n_igs, &bootInfo->chameleonConfig)) { if ((n_igs >= 0) || (n_igs <= 15)) { verbose("AAPL,ig-platform-id was set in org.chameleon.Boot.plist with value %d\n", n_igs); devprop_add_value(device, "AAPL,ig-platform-id", haswell_ig_vals[n_igs], 4); } else { verbose("AAPL,ig-platform-id was set in org.chameleon.Boot.plist with bad value please choose a number between 0 and 15.\n"); } } else { uint32_t ig_platform_id = 0x0000260c; // set the default platform ig devprop_add_value(device, "AAPL,ig-platform-id", (uint8_t *)&ig_platform_id, 4); } devprop_add_value(device, "AAPL00,DualLink", HD4000_vals[10], 4); devprop_add_value(device, "built-in", &BuiltIn, 1); devprop_add_value(device, "class-code", ClassFix, 4); devprop_add_value(device, "hda-gfx", (uint8_t *)"onboard-1", 10); break; default: break; } stringdata = malloc(sizeof(uint8_t) * string->length); if (!stringdata) { printf("No stringdata.\n"); pause(); return false; } verbose("---------------------------------------------\n"); memcpy(stringdata, (uint8_t*)devprop_generate_string(string), string->length); stringlength = string->length; return true; }
//========================================================================== // The 'main' function for the booter. Called by boot0 when booting // from a block device, or by the network booter. // // arguments: // biosdev - Value passed from boot1/NBP to specify the device // that the booter was loaded from. // // If biosdev is kBIOSDevNetwork, then this function will return if // booting was unsuccessful. This allows the PXE firmware to try the // next boot device on its list. void common_boot(int biosdev) { bool quiet; bool firstRun = true; bool instantMenu; bool rescanPrompt; char *bootFile; int status; unsigned int allowBVFlags = kBVFlagSystemVolume | kBVFlagForeignBoot; unsigned int denyBVFlags = kBVFlagEFISystem; unsigned long adler32; // Set reminder to unload the PXE base code. Neglect to unload // the base code will result in a hang or kernel panic. gUnloadPXEOnExit = true; // Record the device that the booter was loaded from. gBIOSDev = biosdev & kBIOSDevMask; // Initialize boot info structure. initKernBootStruct(); initBooterLog(); // Setup VGA text mode. // Not sure if it is safe to call setVideoMode() before the // config table has been loaded. Call video_mode() instead. #if DEBUG printf("before video_mode\n"); #endif video_mode( 2 ); // 80x25 mono text mode. #if DEBUG printf("after video_mode\n"); #endif // Scan and record the system's hardware information. scan_platform(); // First get info for boot volume. scanBootVolumes(gBIOSDev, 0); bvChain = getBVChainForBIOSDev(gBIOSDev); setBootGlobals(bvChain); // Load boot.plist config file status = loadChameleonConfig(&bootInfo->chameleonConfig); if (getBoolForKey(kQuietBootKey, &quiet, &bootInfo->chameleonConfig) && quiet) { gBootMode |= kBootModeQuiet; } // Override firstRun to get to the boot menu instantly by setting "Instant Menu"=y in system config if (getBoolForKey(kInstantMenuKey, &instantMenu, &bootInfo->chameleonConfig) && instantMenu) { firstRun = false; } // Loading preboot ramdisk if exists. loadPrebootRAMDisk(); // Disable rescan option by default gEnableCDROMRescan = false; // Enable it with Rescan=y in system config if (getBoolForKey(kRescanKey, &gEnableCDROMRescan, &bootInfo->chameleonConfig) && gEnableCDROMRescan) { gEnableCDROMRescan = true; } // Ask the user for Rescan option by setting "Rescan Prompt"=y in system config. rescanPrompt = false; if (getBoolForKey(kRescanPromptKey, &rescanPrompt , &bootInfo->chameleonConfig) && rescanPrompt && biosDevIsCDROM(gBIOSDev)) { gEnableCDROMRescan = promptForRescanOption(); } // Enable touching a single BIOS device only if "Scan Single Drive"=y is set in system config. if (getBoolForKey(kScanSingleDriveKey, &gScanSingleDrive, &bootInfo->chameleonConfig) && gScanSingleDrive) { gScanSingleDrive = true; } // Create a list of partitions on device(s). if (gScanSingleDrive) { scanBootVolumes(gBIOSDev, &bvCount); } else { scanDisks(gBIOSDev, &bvCount); } // Create a separated bvr chain using the specified filters. bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount); gBootVolume = selectBootVolume(bvChain); // Intialize module system init_module_system(); #if DEBUG printf(" Default: %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBootVolume, gBootVolume->biosdev, gBootVolume->part_no, gBootVolume->flags); printf(" bt(0,0): %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBIOSBootVolume, gBIOSBootVolume->biosdev, gBIOSBootVolume->part_no, gBIOSBootVolume->flags); getchar(); #endif useGUI = true; // Override useGUI default getBoolForKey(kGUIKey, &useGUI, &bootInfo->chameleonConfig); if (useGUI && initGUI()) { // initGUI() returned with an error, disabling GUI. useGUI = false; } setBootGlobals(bvChain); // Parse args, load and start kernel. while (1) { bool tryresume, tryresumedefault, forceresume; bool usecache = false;//true; const char *val; int len, trycache, ret = -1; long flags, cachetime, kerneltime, exttime, sleeptime, time; void *binary = (void *)kLoadAddr; // additional variable for testing alternate kernel image locations on boot helper partitions. char bootFileSpec[512]; // Initialize globals. sysConfigValid = false; gErrors = false; status = getBootOptions(firstRun); firstRun = false; if (status == -1) continue; status = processBootOptions(); // Status == 1 means to chainboot if ( status == 1 ) break; // Status == -1 means that the config file couldn't be loaded or that gBootVolume is NULL if ( status == -1 ) { // gBootVolume == NULL usually means the user hit escape. if (gBootVolume == NULL) { freeFilteredBVChain(bvChain); if (gEnableCDROMRescan) rescanBIOSDevice(gBIOSDev); bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount); setBootGlobals(bvChain); setupDeviceList(&bootInfo->themeConfig); } continue; } // Other status (e.g. 0) means that we should proceed with boot. // Turn off any GUI elements if ( bootArgs->Video.v_display == GRAPHICS_MODE ) { gui.devicelist.draw = false; gui.bootprompt.draw = false; gui.menu.draw = false; gui.infobox.draw = false; gui.logo.draw = false; drawBackground(); updateVRAM(); } // Find out which version mac os we're booting. getOSVersion(); if (platformCPUFeature(CPU_FEATURE_EM64T)) { archCpuType = CPU_TYPE_X86_64; } else { archCpuType = CPU_TYPE_I386; } if (getValueForKey(karch, &val, &len, &bootInfo->chameleonConfig)) { if (strncmp(val, "i386", 4) == 0) { archCpuType = CPU_TYPE_I386; } } if (getValueForKey(kKernelArchKey, &val, &len, &bootInfo->chameleonConfig)) { if (strncmp(val, "i386", 4) == 0) { archCpuType = CPU_TYPE_I386; } } // Notify modules that we are attempting to boot execute_hook("PreBoot", NULL, NULL, NULL, NULL); if (!getBoolForKey (kWake, &tryresume, &bootInfo->chameleonConfig)) { tryresume = true; tryresumedefault = true; } else { tryresumedefault = false; } if (!getBoolForKey (kForceWake, &forceresume, &bootInfo->chameleonConfig)) { forceresume = false; } if (forceresume) { tryresume = true; tryresumedefault = false; } while (tryresume) { const char *tmp; BVRef bvr; if (!getValueForKey(kWakeImage, &val, &len, &bootInfo->chameleonConfig)) val = "/private/var/vm/sleepimage"; // Do this first to be sure that root volume is mounted ret = GetFileInfo(0, val, &flags, &sleeptime); if ((bvr = getBootVolumeRef(val, &tmp)) == NULL) break; // Can't check if it was hibernation Wake=y is required if (bvr->modTime == 0 && tryresumedefault) break; if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)) break; if (!forceresume && ((sleeptime+3)<bvr->modTime)) { #if DEBUG printf ("Hibernate image is too old by %d seconds. Use ForceWake=y to override\n", bvr->modTime-sleeptime); #endif break; } HibernateBoot((char *)val); break; } getBoolForKey(kUseKernelCache, &usecache, &bootInfo->chameleonConfig); if (usecache) { if( getValueForKey(kKernelCacheKey, &val, &len, &bootInfo->chameleonConfig) || getValueForKey(kKernelCacheKey, &val, &len, &bootInfo->bootConfig) ) { if (val[0] == '\\') { len--; val++; } strlcpy(gBootKernelCacheFile, val, len + 1); verbose("Using kernel cache: \"%s\" \n", gBootKernelCacheFile); //sleep(5); } else { // Lion and Mountain Lion prelink kernel cache file␊ if ((checkOSVersion("10.7")) || (checkOSVersion("10.8"))) { sprintf(gBootKernelCacheFile, "%skernelcache", kDefaultCachePathSnow); } // Snow Leopard else if (checkOSVersion("10.6")) { sprintf(gBootKernelCacheFile, "kernelcache_%s", (archCpuType == CPU_TYPE_I386) ? "i386" : "x86_64"); int lnam = sizeof(gBootKernelCacheFile) + 9; //with adler32 char* name; long prev_time = 0; struct dirstuff* cacheDir = opendir(kDefaultCachePathSnow); while(readdir(cacheDir, (const char**)&name, &flags, &time) >= 0) { if (((flags & kFileTypeMask) != kFileTypeDirectory) && time > prev_time && strstr(name, gBootKernelCacheFile) && (name[lnam] != '.')) { sprintf(gBootKernelCacheFile, "%s%s", kDefaultCachePathSnow, name); prev_time = time; } } } else { // Reset cache name. bzero(gCacheNameAdler + 64, sizeof(gCacheNameAdler) - 64); sprintf(gCacheNameAdler + 64, "%s,%s", gRootDevice, bootInfo->bootFile); adler32 = Adler32((unsigned char *)gCacheNameAdler, sizeof(gCacheNameAdler)); sprintf(gBootKernelCacheFile, "%s.%08lX", kDefaultCachePathLeo, adler32); } } } // Check for cache file. trycache = (usecache && ((gBootMode & kBootModeSafe) == 0) && !gOverrideKernel && (gBootFileType == kBlockDeviceType) && (gMKextName[0] == '\0') && (gBootKernelCacheFile[0] != '\0')); verbose("trycache: %d\n", trycache); verbose("Loading Darwin %s\n", gMacOSVersion); if (trycache) do { verbose("bootInfo->bootFile: \"%s\" \n", bootInfo->bootFile); ret = GetFileInfo(NULL, bootInfo->bootFile, &flags, &kerneltime); if (ret != 0) kerneltime = 0; else if ((flags & kFileTypeMask) != kFileTypeFlat) { trycache = 0; verbose("trycache0 : 1\n"); break; } ret = GetFileInfo(NULL, gBootKernelCacheFile, &flags, &cachetime); if ((ret != 0)) { trycache = 0; verbose("trycache0 : 2.1 \"%s\" \n", gBootKernelCacheFile); break; } else if ( ((flags & kFileTypeMask) != kFileTypeFlat) ) { trycache = 0; verbose("trycache0 : 2.2\n"); break; } else if ( (cachetime < kerneltime) ) { trycache = 0; verbose("trycache0 : 2.3\n"); break; } ret = GetFileInfo("/System/Library/", "Extensions", &flags, &exttime); if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory) && (cachetime < exttime)) { trycache = 0; verbose("trycache0 : 3\n"); break; } if (ret == 0 && kerneltime > exttime) { exttime = kerneltime; } if (ret == 0 && cachetime < (exttime + 1)) { trycache = 0; verbose("trycache0 : 4\n"); break; } } while (0); // sleep(5); do { if (trycache) { bootFile = gBootKernelCacheFile; verbose("Loading kernel cache %s\n", bootFile); if ((checkOSVersion("10.7")) || (checkOSVersion("10.8"))) { ret = LoadThinFatFile(bootFile, &binary); } else { ret = LoadFile(bootFile); binary = (void *)kLoadAddr; } if (ret >= 0) break; verbose("Kernel cache did not load %s\n ", bootFile); } if ((checkOSVersion("10.7")) || (checkOSVersion("10.8"))) { bootFile = gBootKernelCacheFile; } else { sprintf(bootFile, "\%s", bootInfo->bootFile); } // Try to load kernel image from alternate locations on boot helper partitions. sprintf(bootFileSpec, "com.apple.boot.P%s", bootFile); ret = GetFileInfo(NULL, bootFileSpec, &flags, &time); if (ret == -1) { sprintf(bootFileSpec, "com.apple.boot.R%s", bootFile); ret = GetFileInfo(NULL, bootFileSpec, &flags, &time); if (ret == -1) { sprintf(bootFileSpec, "com.apple.boot.S%s", bootFile); ret = GetFileInfo(NULL, bootFileSpec, &flags, &time); if (ret == -1) { // No alternate location found, using the original kernel image path. strcpy(bootFileSpec, bootInfo->bootFile); } } } if ((checkOSVersion("10.7")) || (checkOSVersion("10.8"))) { //Lion, dont load kernel if haz cache if (!trycache) { verbose("Loading kernel %s\n", bootFileSpec); ret = LoadThinFatFile(bootFileSpec, &binary); if (ret <= 0 && archCpuType == CPU_TYPE_X86_64) { archCpuType = CPU_TYPE_I386; ret = LoadThinFatFile(bootFileSpec, &binary); } } else ret = 1; } else { //Snow Leopard or older verbose("Loading kernel %s\n", bootFileSpec); ret = LoadThinFatFile(bootFileSpec, &binary); if (ret <= 0 && archCpuType == CPU_TYPE_X86_64) { archCpuType = CPU_TYPE_I386; ret = LoadThinFatFile(bootFileSpec, &binary); } } } while (0); clearActivityIndicator(); #if DEBUG printf("Pausing..."); sleep(8); #endif if (ret <= 0) { printf("Can't find %s\n", bootFile); sleep(1); if (gBootFileType == kNetworkDeviceType) { // Return control back to PXE. Don't unload PXE base code. gUnloadPXEOnExit = false; break; } } else { /* Won't return if successful. */ ret = ExecKernel(binary); } } // chainboot if (status == 1) { // if we are already in graphics-mode, if (getVideoMode() == GRAPHICS_MODE) { setVideoMode(VGA_TEXT_MODE, 0); // switch back to text mode. } } if ((gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit) { nbpUnloadBaseCode(); } }
void boot(int biosdev) { zeroBSS(); mallocInit(0, 0, 0, mallocError); #if MUST_ENABLE_A20 // Enable A20 gate before accessing memory above 1 MB. if (fastEnableA20() != 0) { enableA20(); // Fast enable failed. Try legacy method. } #endif bool haveCABootPlist = false; bool quietBootMode = true; void *fileLoadBuffer = (void *)kLoadAddr; char bootFile[256]; char rootUUID[37]; char * kernelFlags = NULL; const char * val; int length = 0; int kernelFlagsLength = 0; bootFile[0] = '\0'; rootUUID[0] = '\0'; #if PRE_LINKED_KERNEL_SUPPORT bool mayUseKernelCache = false; long flags, cachetime; #endif initPlatform(biosdev); // Passing on the boot drive. #if DEBUG_STATE_ENABLED // Don't switch graphics mode / show boot logo when DEBUG is set to 1. printf("\ngArchCPUType (CPU): %s\n", (gArchCPUType == CPU_TYPE_X86_64) ? "x86_64" : "i386"); sleep(3); // Silent sleep. #else showBootLogo(); #endif // A bit ugly maybe, but this will be changed sometime soon. while (readKeyboardStatus()) { int key = (bgetc() & 0xff); if ((key |= 0x20) == 'r') { gPlatform.BootRecoveryHD = true; } } initPartitionChain(); #define loadCABootPlist() loadSystemConfig(&bootInfo->bootConfig) // Loading: /Library/Preferences/SystemConfiguration/com.apple.Boot.plist // TODO: Check if everything works <i>without</i> having this plist. if (loadCABootPlist() == STATE_SUCCESS) { _BOOT_DEBUG_DUMP("com.apple.Boot.plist located.\n"); // Load successful. Change state accordantly. haveCABootPlist = true; // Checked <i>before</i> calling key functions. // Check the value of <key>Kernel Flags</key> for stuff we are interested in. // Note: We need to know about: arch= and the boot flags: -s, -v, -f and -x if (getValueForKey(kKernelFlagsKey, &val, &kernelFlagsLength, &bootInfo->bootConfig)) { // "Kernel Flags" key found. Check length to see if we have anything to work with. if (kernelFlagsLength) { kernelFlagsLength++; // Yes. Allocate memory for it and copy the kernel flags into it. kernelFlags = malloc(kernelFlagsLength); strlcpy(kernelFlags, val, kernelFlagsLength); // Is 'arch=<i386/x86_64>' specified as kernel flag? if (getValueForBootKey(kernelFlags, "arch", &val, &length)) // && len >= 4) { gArchCPUType = (strncmp(val, "x86_64", 6) == 0) ? CPU_TYPE_X86_64 : CPU_TYPE_I386; _BOOT_DEBUG_DUMP("gArchCPUType (c.a.B.plist): %s\n", (gArchCPUType == CPU_TYPE_X86_64) ? "x86_64" : "i386"); } // Check for -v (verbose) and -s (single user mode) flags. gVerboseMode = getValueForBootKey(kernelFlags, kVerboseModeFlag, &val, &length) || getValueForBootKey(kernelFlags, kSingleUserModeFlag, &val, &length); if (gVerboseMode) { #if DEBUG_BOOT == false setVideoMode(VGA_TEXT_MODE); #endif } // Check for -x (safe) and -f (flush cache) flags. if (getValueForBootKey(kernelFlags, kSafeModeFlag, &val, &length) || getValueForBootKey(kernelFlags, kIgnoreCachesFlag, &val, &length)) { gBootMode = kBootModeSafe; } // Is 'boot-uuid=<value>' specified as kernel flag? if (getValueForBootKey(kernelFlags, kBootUUIDKey, &val, &length) && length == 36) { _BOOT_DEBUG_DUMP("Target boot-uuid=<%s>\n", val); // Yes. Copy its value into rootUUID. strlcpy(rootUUID, val, 37); } /* else { strlcpy(rootUUID, "3453E0E5-017B-38AD-A0AA-D0BBD8565D6", 37); _BOOT_DEBUG_DUMP("Target boot-uuid=<%s>\n", rootUUID); } */ } } #if PRE_LINKED_KERNEL_SUPPORT /* Look for 'Kernel Cache' key. */ if (getValueForKey(kKernelCacheKey, &val, &length, &bootInfo->bootConfig)) { _BOOT_DEBUG_DUMP("Kernel Cache set to: %s\n", val); // Key found. Check if the given filepath/name exists. if (length && GetFileInfo(NULL, val, &flags, &cachetime) == 0) { // File located. Init kernelCacheFile so that we can use it as boot file. gPlatform.KernelCachePath = strdup(val); // Set flag to inform the load process to skip parts of the code. gPlatform.KernelCacheSpecified = true; _BOOT_DEBUG_DUMP("kernelcache file found.\n"); } _BOOT_DEBUG_ELSE_DUMP("Error: kernelcache file not found.\n"); } // _BOOT_DEBUG_ELSE_DUMP("No 'Kernel Cache' key given.\n"); #endif /* Enable touching of a single BIOS device by setting 'Scan Single Drive' to yes. if (getBoolForKey(kScanSingleDriveKey, &gScanSingleDrive, &bootInfo->bootConfig) && gScanSingleDrive) { gScanSingleDrive = true; } */ } else { _BOOT_DEBUG_DUMP("No com.apple.Boot.plist found.\n"); } // Was a target drive (per UUID) specified in com.apple.Boot.plist? if (rootUUID[0] == '\0') { _BOOT_DEBUG_DUMP("No UUID specified in com.apple.Boot.plist\n"); // No, so are we booting from a System Volume? if (gPlatform.BootVolume->flags & kBVFlagSystemVolume) { _BOOT_DEBUG_DUMP("Booting from a System Volume, getting UUID.\n"); // Yes, then let's get the UUID. if (HFSGetUUID(gPlatform.BootVolume, rootUUID) == STATE_SUCCESS) { _BOOT_DEBUG_DUMP("Success [%s]\n", rootUUID); } } else // Booting from USB-stick or SDboot media. { _BOOT_DEBUG_DUMP("Booting from a Non System Volume, getting UUID.\n"); // Get target System Volume and UUID in one go. BVRef rootVolume = getTargetRootVolume(rootUUID); if (rootVolume) { _BOOT_DEBUG_DUMP("Success [%s]\n", rootUUID); gPlatform.RootVolume = rootVolume; } } // This should never happen, but just to be sure. if (rootUUID[0] == '\0') { _BOOT_DEBUG_DUMP("Failed to get UUID for System Volume.\n"); if (!gVerboseMode) { // Force verbose mode when we didn't find a UUID, so // that people see what is going on in times of trouble. gVerboseMode = true; } } } /* * At this stage we know exactly what boot mode we're in, and which disk to boot from * any of which may or may not have been set/changed (in com.apple.Boot.plist) into a * non-default system setting and thus is this the place to update our EFI tree. */ updateEFITree(rootUUID); if (haveCABootPlist) // Check boolean before doing more time consuming tasks. { if (getBoolForKey(kQuietBootKey, &quietBootMode, &bootInfo->bootConfig) && !quietBootMode) { gBootMode = kBootModeNormal; // Reversed from: gBootMode |= kBootModeQuiet; } } // Parse args, load and start kernel. while (1) { // Initialize globals. sysConfigValid = 0; gErrors = 0; int retStatus = -1; getAndProcessBootArguments(kernelFlags); // Initialize bootFile (defaults to: mach_kernel). strcpy(bootFile, bootInfo->bootFile); #if PRE_LINKED_KERNEL_SUPPORT _BOOT_DEBUG_DUMP("gBootMode = %d\n", gBootMode); // Preliminary checks to prevent us from doing useless things. mayUseKernelCache = ((gBootMode & kBootModeSafe) == 0); _BOOT_DEBUG_DUMP("mayUseKernelCache = %s\n", mayUseKernelCache ? "true" : "false"); /* * A pre-linked kernel, or kernelcache, requires you to have all essential kexts for your * configuration, including FakeSMC.kext in: /System/Library/Extensions/ * Not in /Extra/Extensions/ because this directory will be ignored, completely when a * pre-linked kernel or kernelcache is used! * * Note: Not following this word of advise will render your system incapable of booting! */ if (mayUseKernelCache == false) { _BOOT_DEBUG_DUMP("Warning: kernelcache will be ignored!\n"); // True when 'Kernel Cache' is set in com.apple.Boot.plist if (gPlatform.KernelCacheSpecified == true) { sprintf(bootFile, "%s", bootInfo->bootFile); } } else { // True when 'Kernel Cache' is set in com.apple.Boot.plist if (gPlatform.KernelCacheSpecified == true) { _BOOT_DEBUG_DUMP("kernelcache: %s\n", gPlatform.KernelCachePath); /* * Starting with Lion, we can take a shortcut by simply pointing * the 'bootFile' to the kernel cache and we are done. */ sprintf(bootFile, "%s", gPlatform.KernelCachePath); } /* * We might have been fired up from a USB thumbdrive (kickstart boot) and * thus we have to check the kernel cache path first (might not be there). */ else if (GetFileInfo(NULL, gPlatform.KernelCachePath, &flags, &cachetime) == 0) { #if ((MAKE_TARGET_OS & LION) == LION) // Also for Mountain Lion, which has bit 2 set like Lion. _BOOT_DEBUG_DUMP("Checking for kernelcache...\n"); if (GetFileInfo(gPlatform.KernelCachePath, (char *)kKernelCache, &flags, &cachetime) == 0) { sprintf(bootFile, "%s/%s", gPlatform.KernelCachePath, kKernelCache); _BOOT_DEBUG_DUMP("Kernelcache located.\n"); } _BOOT_DEBUG_ELSE_DUMP("Failed to locate the kernelcache. Will load: %s!\n", bootInfo->bootFile); } _BOOT_DEBUG_ELSE_DUMP("Failed to locate the kernelcache (directory)!\n"); } #else // Not for (Mountain) Lion, go easy with the Snow Leopard. static char preLinkedKernelPath[128]; static char adler32Key[PLATFORM_NAME_LEN + ROOT_PATH_LEN]; unsigned long adler32 = 0; preLinkedKernelPath[0] = '\0'; _BOOT_DEBUG_DUMP("Checking for pre-linked kernel...\n"); // Zero out platform info (name and kernel root path). bzero(adler32Key, sizeof(adler32Key)); // Construct key for the pre-linked kernel checksum (generated by adler32). sprintf(adler32Key, gPlatform.ModelID); sprintf(adler32Key + PLATFORM_NAME_LEN, "%s", BOOT_DEVICE_PATH); sprintf(adler32Key + (PLATFORM_NAME_LEN + 38), "%s", bootInfo->bootFile); adler32 = Adler32((unsigned char *)adler32Key, sizeof(adler32Key)); _BOOT_DEBUG_DUMP("adler32: %08X\n", adler32); // Create path to pre-linked kernel. sprintf(preLinkedKernelPath, "%s/%s_%s.%08lX", gPlatform.KernelCachePath, kKernelCache, ((gArchCPUType == CPU_TYPE_X86_64) ? "x86_64" : "i386"), adler32); // Check if this file exists. if ((GetFileInfo(NULL, preLinkedKernelPath, &flags, &cachetime) == 0) && ((flags & kFileTypeMask) == kFileTypeFlat)) { _BOOT_DEBUG_DUMP("Pre-linked kernel cache located!\nLoading pre-linked kernel: %s\n", preLinkedKernelPath); // Returns -1 on error, or the actual filesize. if (LoadFile((const char *)preLinkedKernelPath)) { retStatus = 1; fileLoadBuffer = (void *)kLoadAddr; bootFile[0] = 0; } _BOOT_DEBUG_ELSE_DUMP("Failed to load the pre-linked kernel. Will load: %s!\n", bootInfo->bootFile); } _BOOT_DEBUG_ELSE_DUMP("Failed to locate the pre-linked kernel!\n"); } _BOOT_DEBUG_ELSE_DUMP("Failed to locate the cache directory!\n"); }
int getBootOptions(bool firstRun) { int i; int key; int nextRow; int timeout; #if UNUSED int bvCount; #endif BVRef bvr; BVRef menuBVR; bool showPrompt, newShowPrompt, isCDROM; int optionKey; // Initialize default menu selection entry. menuBVR = selectBootVolume(getBvChain()); safe_set_env(envgBootVolume, (uint32_t)menuBVR); if (biosDevIsCDROM((int)get_env(envgBIOSDev))) { isCDROM = true; } else { isCDROM = false; } // Clear command line boot arguments clearBootArgs(); // Allow user to override default timeout. #if UNUSED if (multiboot_timeout_set) { timeout = multiboot_timeout; } else #endif if (!getIntForKey(kTimeoutKey, &timeout, DEFAULT_BOOT_CONFIG)) { /* If there is no timeout key in the file use the default timeout which is different for CDs vs. hard disks. However, if not booting a CD and no config file could be loaded set the timeout to zero which causes the menu to display immediately. This way, if no partitions can be found, that is the disk is unpartitioned or simply cannot be read) then an empty menu is displayed. If some partitions are found, for example a Windows partition, then these will be displayed in the menu as foreign partitions. */ if (isCDROM) { timeout = kCDBootTimeout; } else { timeout = get_env(envSysConfigValid) ? kBootTimeout : 0; } } long gBootMode = (long)get_env(envgBootMode); if (timeout < 0) { gBootMode |= kBootModeQuiet; safe_set_env(envgBootMode,gBootMode); } // If the user is holding down a modifier key, enter safe mode. if ((readKeyboardShiftFlags() & 0x0F) != 0) { gBootMode |= kBootModeSafe; safe_set_env(envgBootMode,gBootMode); } // Checking user pressed keys bool f8press = false, spress = false, vpress = false; while (readKeyboardStatus()) { key = bgetc (); if (key == 0x4200) f8press = true; if ((key & 0xff) == 's' || (key & 0xff) == 'S') spress = true; if ((key & 0xff) == 'v' || (key & 0xff) == 'V') vpress = true; } // If user typed F8, abort quiet mode, and display the menu. if (f8press) { gBootMode &= ~kBootModeQuiet; safe_set_env(envgBootMode,gBootMode); timeout = 0; } // If user typed 'v' or 'V', boot in verbose mode. if ((gBootMode & kBootModeQuiet) && firstRun && vpress) { addBootArg(kVerboseModeFlag); } // If user typed 's' or 'S', boot in single user mode. if ((gBootMode & kBootModeQuiet) && firstRun && spress) { addBootArg(kSingleUserModeFlag); } setCursorPosition(0, 0, 0); clearScreenRows(0, kScreenLastRow); if (!(gBootMode & kBootModeQuiet)) { // Display banner and show hardware info. char * bootBanner = (char*)(uint32_t)get_env(envBootBanner); printf(bootBanner, (int)(get_env(envConvMem) + get_env(envExtMem)) / 1024); } changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0); msglog("Scanning device %x...", (uint32_t)get_env(envgBIOSDev)); // When booting from CD, default to hard drive boot when possible. if (isCDROM && firstRun) { const char *val; char *prompt = NULL; char *name = NULL; int cnt; if (getValueForKey(kCDROMPromptKey, &val, &cnt, DEFAULT_BOOT_CONFIG)) { prompt = calloc(cnt + 1, sizeof(char)); if (!prompt) { stop("Couldn't allocate memory for the prompt\n"); //TODO: Find a better stategie return -1; } strncat(prompt, val, cnt); } else { prompt = calloc(256, sizeof(char)); if (!prompt) { stop("Couldn't allocate memory for the prompt\n"); //TODO: Find a better stategie return -1; } BVRef bvr; if (( bvr = ((BVRef)(uint32_t)get_env(envgBootVolume)))) { name = calloc(80, sizeof(char)); if (!name) { stop("Couldn't allocate memory for the device name\n"); //TODO: Find a better stategie return -1; } getBootVolumeDescription(bvr, name, 79, false); snprintf(prompt, 256,"Press ENTER to start up from %s, or press any key to enter startup options.", name); free(name); } else snprintf(prompt, 256,"Press ENTER to start up, or press any key to enter startup options."); } if (getIntForKey( kCDROMOptionKey, &optionKey, DEFAULT_BOOT_CONFIG )) { // The key specified is a special key. } else { // Default to F8. optionKey = 0x4200; } // If the timeout is zero then it must have been set above due to the // early catch of F8 which means the user wants to set boot options // which we ought to interpret as meaning he wants to boot the CD. if (timeout != 0) { key = countdown(prompt, kMenuTopRow, timeout, &optionKey); } else { key = optionKey; } if (prompt != NULL) { free(prompt); } clearScreenRows( kMenuTopRow, kMenuTopRow + 2 ); do { // Hit the option key ? if (key == optionKey) { if (key != 0x1C0D) { gBootMode &= ~kBootModeQuiet; safe_set_env(envgBootMode,gBootMode); timeout = 0; break; } } key = key & 0xFF; // Try booting hard disk if user pressed 'h' if (biosDevIsCDROM((int)get_env(envgBIOSDev)) && key == 'h') { BVRef bvr; // Look at partitions hosting OS X other than the CD-ROM for (bvr = getBvChain(); bvr; bvr=bvr->next) { if ((bvr->flags & kBVFlagSystemVolume) && bvr->biosdev != (int)get_env(envgBIOSDev)) { safe_set_env(envgBootVolume, (uint32_t)bvr); } } } goto done; } while (0); } if (get_env(envgBootMode) & kBootModeQuiet) { // No input allowed from user. goto done; } if (firstRun && timeout > 0 ) { key = countdown("Press ENTER to start up, or press any key to enter startup options.", kMenuTopRow, timeout, &optionKey); if (key == 0x1C0D) { goto done; } else if (key == 0) { // If the user is holding down a modifier key, // enter safe mode. if ((readKeyboardShiftFlags() & 0x0F) != 0) { gBootMode |= kBootModeSafe; safe_set_env(envgBootMode,gBootMode); } goto done; } } int devcnt = (int)get_env(envgDeviceCount); if (devcnt) { // Allocate memory for an array of menu items. menuItems = calloc(devcnt,sizeof(MenuItem)); if (menuItems == NULL) { goto done; } // Associate a menu item for each BVRef. for (bvr=getBvChain(), i=devcnt-1, selectIndex=0; bvr; bvr=bvr->next) { if (bvr->visible) { getBootVolumeDescription(bvr, menuItems[i].name, sizeof(menuItems[i].name) - 1, true); menuItems[i].param = (void *) bvr; if (bvr == menuBVR) { selectIndex = i; } i--; } } } // Clear screen and hide the blinking cursor. clearScreenRows(kMenuTopRow, kMenuTopRow + 2); changeCursor(0, kMenuTopRow, kCursorTypeHidden, 0); nextRow = kMenuTopRow; /*showPrompt = true;*/ if (devcnt) { printf("Use \30\31 keys to select the startup volume."); showMenu( menuItems, devcnt, selectIndex, kMenuTopRow + 2, kMenuMaxItems ); nextRow += min( devcnt, kMenuMaxItems ) + 3; } // Show the boot prompt. showPrompt = (devcnt == 0) || (menuBVR->flags & kBVFlagNativeBoot); showBootPrompt( nextRow, showPrompt ); do { key = getc(); updateMenu( key, (void **) &menuBVR ); newShowPrompt = (devcnt == 0) || (menuBVR->flags & kBVFlagNativeBoot); if (newShowPrompt != showPrompt) { showPrompt = newShowPrompt; showBootPrompt( nextRow, showPrompt ); } if (showPrompt) { updateBootArgs(key); } switch (key) { case kReturnKey: if (*gBootArgs == '?') { char * argPtr = gBootArgs; // Skip the leading "?" character. argPtr++; getNextArg(&argPtr, booterCommand); getNextArg(&argPtr, booterParam); /* * TODO: this needs to be refactored. */ #if UNUSED if (strncmp( booterCommand, "video", sizeof("video") ) == 0) { printVBEModeInfo(); } else #endif if ( strncmp( booterCommand, "memory", sizeof("memory") ) == 0) { printMemoryInfo(); } else if (strncmp(booterCommand, "lspci", sizeof( "lspci")) == 0) { lspci(); } else if (strncmp(booterCommand, "more", sizeof("more")) == 0) { showTextFile(booterParam); } else if (strncmp(booterCommand, "rd", sizeof("rd")) == 0) { if (execute_hook("processRAMDiskCommand", (void*)argPtr, &booterParam, NULL, NULL, NULL, NULL) != EFI_SUCCESS) showMessage("ramdisk module not found, please install RamdiskLoader.dylib in /Extra/modules/"); } else if (strncmp(booterCommand, "norescan", sizeof("norescan")) == 0) { if (get_env(envgEnableCDROMRescan)) { safe_set_env(envgEnableCDROMRescan,false); break; } } else { showHelp(); } key = 0; showBootPrompt(nextRow, showPrompt); break; } safe_set_env(envgBootVolume, (uint32_t)menuBVR); setRootVolume(menuBVR); safe_set_env(envgBIOSDev,menuBVR->biosdev); break; case kEscapeKey: clearBootArgs(); break; case kF5Key: // New behavior: // Clear gBootVolume to restart the loop // if the user enabled rescanning the optical drive. // Otherwise boot the default boot volume. if (get_env(envgEnableCDROMRescan)) { //gBootVolume = NULL; safe_set_env(envgBootVolume, (uint32_t)NULL); clearBootArgs(); } break; case kF10Key: safe_set_env(envgScanSingleDrive, false); scanDisks(); //gBootVolume = NULL; safe_set_env(envgBootVolume, (uint32_t)NULL); clearBootArgs(); break; default: key = 0; break; } } while (0 == key); done: if (bootArgs->Video.v_display == VGA_TEXT_MODE) { clearScreenRows(kMenuTopRow, kScreenLastRow); changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0); } safe_set_env(envShouldboot, false); if (menuItems) { free(menuItems); menuItems = NULL; } return 0; }
/* * Calculates the FSB and CPU frequencies using specific MSRs for each CPU * - multi. is read from a specific MSR. In the case of Intel, there is: * a max multi. (used to calculate the FSB freq.), * and a current multi. (used to calculate the CPU freq.) * - fsbFrequency = tscFrequency / multi * - cpuFrequency = fsbFrequency * multi */ void scan_cpu(PlatformInfo_t *p) { uint64_t tscFrequency = 0; uint64_t fsbFrequency = 0; uint64_t cpuFrequency = 0; uint64_t msr = 0; uint64_t flex_ratio = 0; uint32_t max_ratio = 0; uint32_t min_ratio = 0; uint8_t bus_ratio_max = 0; uint8_t currdiv = 0; uint8_t currcoef = 0; uint8_t maxdiv = 0; uint8_t maxcoef = 0; const char *newratio; int len = 0; int myfsb = 0; uint8_t bus_ratio_min = 0; uint32_t reg[4]; char str[128]; /* get cpuid values */ do_cpuid(0x00000000, p->CPU.CPUID[CPUID_0]); do_cpuid(0x00000001, p->CPU.CPUID[CPUID_1]); do_cpuid(0x00000002, p->CPU.CPUID[CPUID_2]); do_cpuid(0x00000003, p->CPU.CPUID[CPUID_3]); do_cpuid2(0x00000004, 0, p->CPU.CPUID[CPUID_4]); do_cpuid(0x80000000, p->CPU.CPUID[CPUID_80]); if (p->CPU.CPUID[CPUID_0][0] >= 0x5) { do_cpuid(5, p->CPU.CPUID[CPUID_5]); } if (p->CPU.CPUID[CPUID_0][0] >= 6) { do_cpuid(6, p->CPU.CPUID[CPUID_6]); } if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 8) { do_cpuid(0x80000008, p->CPU.CPUID[CPUID_88]); do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]); } else if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 1) { do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]); } // #if DEBUG_CPU { int i; DBG("CPUID Raw Values:\n"); for (i = 0; i < CPUID_MAX; i++) { DBG("%02d: %08x-%08x-%08x-%08x\n", i, p->CPU.CPUID[i][0], p->CPU.CPUID[i][1], p->CPU.CPUID[i][2], p->CPU.CPUID[i][3]); } } // #endif /* EAX (Intel): 31 28 27 20 19 16 1514 1312 11 8 7 4 3 0 +--------+----------------+--------+----+----+--------+--------+--------+ |########|Extended family |Extmodel|####|type|familyid| model |stepping| +--------+----------------+--------+----+----+--------+--------+--------+ EAX (AMD): 31 28 27 20 19 16 1514 1312 11 8 7 4 3 0 +--------+----------------+--------+----+----+--------+--------+--------+ |########|Extended family |Extmodel|####|####|familyid| model |stepping| +--------+----------------+--------+----+----+--------+--------+--------+ */ p->CPU.Vendor = p->CPU.CPUID[CPUID_0][1]; p->CPU.Signature = p->CPU.CPUID[CPUID_1][0]; p->CPU.Stepping = (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 3, 0); // stepping = cpu_feat_eax & 0xF; p->CPU.Model = (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 7, 4); // model = (cpu_feat_eax >> 4) & 0xF; p->CPU.Family = (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 11, 8); // family = (cpu_feat_eax >> 8) & 0xF; //p->CPU.Type = (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 13, 12); // type = (cpu_feat_eax >> 12) & 0x3; p->CPU.ExtModel = (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 19, 16); // ext_model = (cpu_feat_eax >> 16) & 0xF; p->CPU.ExtFamily = (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 27, 20); // ext_family = (cpu_feat_eax >> 20) & 0xFF; p->CPU.Model += (p->CPU.ExtModel << 4); if (p->CPU.Vendor == CPUID_VENDOR_INTEL) { /* * Find the number of enabled cores and threads * (which determines whether SMT/Hyperthreading is active). */ switch (p->CPU.Model) { case CPU_MODEL_NEHALEM: case CPU_MODEL_FIELDS: case CPU_MODEL_DALES: case CPU_MODEL_NEHALEM_EX: case CPU_MODEL_JAKETOWN: case CPU_MODEL_SANDYBRIDGE: case CPU_MODEL_IVYBRIDGE: case CPU_MODEL_HASWELL: case CPU_MODEL_HASWELL_SVR: //case CPU_MODEL_HASWELL_H: case CPU_MODEL_HASWELL_ULT: case CPU_MODEL_CRYSTALWELL: msr = rdmsr64(MSR_CORE_THREAD_COUNT); p->CPU.NoCores = (uint8_t)bitfield((uint32_t)msr, 31, 16); p->CPU.NoThreads = (uint8_t)bitfield((uint32_t)msr, 15, 0); break; case CPU_MODEL_DALES_32NM: case CPU_MODEL_WESTMERE: case CPU_MODEL_WESTMERE_EX: msr = rdmsr64(MSR_CORE_THREAD_COUNT); p->CPU.NoCores = (uint8_t)bitfield((uint32_t)msr, 19, 16); p->CPU.NoThreads = (uint8_t)bitfield((uint32_t)msr, 15, 0); break; default: p->CPU.NoCores = 0; break; } // end switch } if (p->CPU.NoCores == 0) { p->CPU.NoCores = (uint8_t)(p->CPU.CoresPerPackage & 0xff); p->CPU.NoThreads = (uint8_t)(p->CPU.LogicalPerPackage & 0xff); } /* get BrandString (if supported) */ /* Copyright: from Apple's XNU cpuid.c */ if (p->CPU.CPUID[CPUID_80][0] > 0x80000004) { char *s; bzero(str, 128); /* * The BrandString 48 bytes (max), guaranteed to * be NULL terminated. */ do_cpuid(0x80000002, reg); memcpy(&str[0], (char *)reg, 16); do_cpuid(0x80000003, reg); memcpy(&str[16], (char *)reg, 16); do_cpuid(0x80000004, reg); memcpy(&str[32], (char *)reg, 16); for (s = str; *s != '\0'; s++) { if (*s != ' ') { break; } } strlcpy(p->CPU.BrandString, s, 48); if (!strncmp(p->CPU.BrandString, CPU_STRING_UNKNOWN, MIN(sizeof(p->CPU.BrandString), strlen(CPU_STRING_UNKNOWN) + 1))) { /* * This string means we have a firmware-programmable brand string, * and the firmware couldn't figure out what sort of CPU we have. */ p->CPU.BrandString[0] = '\0'; } p->CPU.BrandString[47] = '\0'; // DBG("Brandstring = %s\n", p->CPU.BrandString); } //workaround for N270. I don't know why it detected wrong // MSR is *NOT* available on the Intel Atom CPU if ((p->CPU.Model == CPU_MODEL_ATOM) && (strstr(p->CPU.BrandString, "270"))) { p->CPU.NoCores = 1; p->CPU.NoThreads = 2; } if (p->CPU.Vendor == CPUID_VENDOR_AMD) { p->CPU.NoThreads = (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16); p->CPU.NoCores = (uint8_t)bitfield(p->CPU.CPUID[CPUID_88][2], 7, 0) + 1; } /* setup features */ if ((bit(23) & p->CPU.CPUID[CPUID_1][3]) != 0) { p->CPU.Features |= CPU_FEATURE_MMX; } if ((bit(25) & p->CPU.CPUID[CPUID_1][3]) != 0) { p->CPU.Features |= CPU_FEATURE_SSE; } if ((bit(26) & p->CPU.CPUID[CPUID_1][3]) != 0) { p->CPU.Features |= CPU_FEATURE_SSE2; } if ((bit(0) & p->CPU.CPUID[CPUID_1][2]) != 0) { p->CPU.Features |= CPU_FEATURE_SSE3; } if ((bit(19) & p->CPU.CPUID[CPUID_1][2]) != 0) { p->CPU.Features |= CPU_FEATURE_SSE41; } if ((bit(20) & p->CPU.CPUID[CPUID_1][2]) != 0) { p->CPU.Features |= CPU_FEATURE_SSE42; } if ((bit(29) & p->CPU.CPUID[CPUID_81][3]) != 0) { p->CPU.Features |= CPU_FEATURE_EM64T; } if ((bit(5) & p->CPU.CPUID[CPUID_1][3]) != 0) { p->CPU.Features |= CPU_FEATURE_MSR; } //if ((bit(28) & p->CPU.CPUID[CPUID_1][3]) != 0) { if (p->CPU.NoThreads > p->CPU.NoCores) { p->CPU.Features |= CPU_FEATURE_HTT; } tscFrequency = measure_tsc_frequency(); DBG("cpu freq classic = 0x%016llx\n", tscFrequency); /* if usual method failed */ if ( tscFrequency < 1000 ) //TEST { tscFrequency = timeRDTSC() * 20;//measure_tsc_frequency(); // DBG("cpu freq timeRDTSC = 0x%016llx\n", tscFrequency); } else { // DBG("cpu freq timeRDTSC = 0x%016llxn", timeRDTSC() * 20); } fsbFrequency = 0; cpuFrequency = 0; if (p->CPU.Vendor == CPUID_VENDOR_INTEL && ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0c) || (p->CPU.Family == 0x0f && p->CPU.Model >= 0x03))) { int intelCPU = p->CPU.Model; if (p->CPU.Family == 0x06) { /* Nehalem CPU model */ switch (p->CPU.Model) { case CPU_MODEL_NEHALEM: case CPU_MODEL_FIELDS: case CPU_MODEL_DALES: case CPU_MODEL_DALES_32NM: case CPU_MODEL_WESTMERE: case CPU_MODEL_NEHALEM_EX: case CPU_MODEL_WESTMERE_EX: /* --------------------------------------------------------- */ case CPU_MODEL_SANDYBRIDGE: case CPU_MODEL_JAKETOWN: case CPU_MODEL_IVYBRIDGE_XEON: case CPU_MODEL_IVYBRIDGE: case CPU_MODEL_HASWELL: case CPU_MODEL_HASWELL_SVR: case CPU_MODEL_HASWELL_ULT: case CPU_MODEL_CRYSTALWELL: /* --------------------------------------------------------- */ msr = rdmsr64(MSR_PLATFORM_INFO); DBG("msr(%d): platform_info %08x\n", __LINE__, bitfield(msr, 31, 0)); bus_ratio_max = bitfield(msr, 15, 8); bus_ratio_min = bitfield(msr, 47, 40); //valv: not sure about this one (Remarq.1) msr = rdmsr64(MSR_FLEX_RATIO); DBG("msr(%d): flex_ratio %08x\n", __LINE__, bitfield(msr, 31, 0)); if (bitfield(msr, 16, 16)) { flex_ratio = bitfield(msr, 15, 8); /* bcc9: at least on the gigabyte h67ma-ud2h, where the cpu multipler can't be changed to allow overclocking, the flex_ratio msr has unexpected (to OSX) contents. These contents cause mach_kernel to fail to compute the bus ratio correctly, instead causing the system to crash since tscGranularity is inadvertently set to 0. */ if (flex_ratio == 0) { /* Clear bit 16 (evidently the presence bit) */ wrmsr64(MSR_FLEX_RATIO, (msr & 0xFFFFFFFFFFFEFFFFULL)); msr = rdmsr64(MSR_FLEX_RATIO); DBG("Unusable flex ratio detected. Patched MSR now %08x\n", bitfield(msr, 31, 0)); } else { if (bus_ratio_max > flex_ratio) { bus_ratio_max = flex_ratio; } } } if (bus_ratio_max) { fsbFrequency = (tscFrequency / bus_ratio_max); } //valv: Turbo Ratio Limit if ((intelCPU != 0x2e) && (intelCPU != 0x2f)) { msr = rdmsr64(MSR_TURBO_RATIO_LIMIT); cpuFrequency = bus_ratio_max * fsbFrequency; max_ratio = bus_ratio_max * 10; } else { cpuFrequency = tscFrequency; } if ((getValueForKey(kbusratio, &newratio, &len, &bootInfo->chameleonConfig)) && (len <= 4)) { max_ratio = atoi(newratio); max_ratio = (max_ratio * 10); if (len >= 3) { max_ratio = (max_ratio + 5); } verbose("Bus-Ratio: min=%d, max=%s\n", bus_ratio_min, newratio); // extreme overclockers may love 320 ;) if ((max_ratio >= min_ratio) && (max_ratio <= 320)) { cpuFrequency = (fsbFrequency * max_ratio) / 10; if (len >= 3) { maxdiv = 1; } else { maxdiv = 0; } } else { max_ratio = (bus_ratio_max * 10); } } //valv: to be uncommented if Remarq.1 didn't stick /*if (bus_ratio_max > 0) bus_ratio = flex_ratio;*/ p->CPU.MaxRatio = max_ratio; p->CPU.MinRatio = min_ratio; myfsb = fsbFrequency / 1000000; verbose("Sticking with [BCLK: %dMhz, Bus-Ratio: %d]\n", myfsb, max_ratio/10); // Bungo: fixed wrong Bus-Ratio readout currcoef = bus_ratio_max; break; default: msr = rdmsr64(MSR_IA32_PERF_STATUS); DBG("msr(%d): ia32_perf_stat 0x%08x\n", __LINE__, bitfield(msr, 31, 0)); currcoef = bitfield(msr, 12, 8); // Bungo: reverted to 2263 state because of wrong old CPUs freq. calculating /* Non-integer bus ratio for the max-multi*/ maxdiv = bitfield(msr, 46, 46); /* Non-integer bus ratio for the current-multi (undocumented)*/ currdiv = bitfield(msr, 14, 14); // This will always be model >= 3 if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0e) || (p->CPU.Family == 0x0f)) { /* On these models, maxcoef defines TSC freq */ maxcoef = bitfield(msr, 44, 40); } else { /* On lower models, currcoef defines TSC freq */ /* XXX */ maxcoef = currcoef; } if (maxcoef) { if (maxdiv) { fsbFrequency = ((tscFrequency * 2) / ((maxcoef * 2) + 1)); } else { fsbFrequency = (tscFrequency / maxcoef); } if (currdiv) { cpuFrequency = (fsbFrequency * ((currcoef * 2) + 1) / 2); } else { cpuFrequency = (fsbFrequency * currcoef); } DBG("max: %d%s current: %d%s\n", maxcoef, maxdiv ? ".5" : "",currcoef, currdiv ? ".5" : ""); } break; } } /* Mobile CPU */ if (rdmsr64(MSR_IA32_PLATFORM_ID) & (1<<28)) { p->CPU.Features |= CPU_FEATURE_MOBILE; } } else if ((p->CPU.Vendor == CPUID_VENDOR_AMD) && (p->CPU.Family == 0x0f)) { switch(p->CPU.ExtFamily) { case 0x00: /* K8 */ msr = rdmsr64(K8_FIDVID_STATUS); maxcoef = bitfield(msr, 21, 16) / 2 + 4; currcoef = bitfield(msr, 5, 0) / 2 + 4; break; case 0x01: /* K10 */ msr = rdmsr64(K10_COFVID_STATUS); do_cpuid2(0x00000006, 0, p->CPU.CPUID[CPUID_6]); // EffFreq: effective frequency interface if (bitfield(p->CPU.CPUID[CPUID_6][2], 0, 0) == 1) { //uint64_t mperf = measure_mperf_frequency(); uint64_t aperf = measure_aperf_frequency(); cpuFrequency = aperf; } // NOTE: tsc runs at the maccoeff (non turbo) // *not* at the turbo frequency. maxcoef = bitfield(msr, 54, 49) / 2 + 4; currcoef = bitfield(msr, 5, 0) + 0x10; currdiv = 2 << bitfield(msr, 8, 6); break; case 0x05: /* K14 */ msr = rdmsr64(K10_COFVID_STATUS); currcoef = (bitfield(msr, 54, 49) + 0x10) << 2; currdiv = (bitfield(msr, 8, 4) + 1) << 2; currdiv += bitfield(msr, 3, 0); break; case 0x02: /* K11 */ // not implimented break; } if (maxcoef) { if (currdiv) { if (!currcoef) { currcoef = maxcoef; } if (!cpuFrequency) { fsbFrequency = ((tscFrequency * currdiv) / currcoef); } else { fsbFrequency = ((cpuFrequency * currdiv) / currcoef); } DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv); } else { if (!cpuFrequency) { fsbFrequency = (tscFrequency / maxcoef); } else { fsbFrequency = (cpuFrequency / maxcoef); } DBG("%d\n", currcoef); } } else if (currcoef) { if (currdiv) { fsbFrequency = ((tscFrequency * currdiv) / currcoef); DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv); } else { fsbFrequency = (tscFrequency / currcoef); DBG("%d\n", currcoef); } } if (!cpuFrequency) cpuFrequency = tscFrequency; } #if 0 if (!fsbFrequency) { fsbFrequency = (DEFAULT_FSB * 1000); cpuFrequency = tscFrequency; DBG("0 ! using the default value for FSB !\n"); } DBG("cpu freq = 0x%016llxn", timeRDTSC() * 20); #endif p->CPU.MaxCoef = maxcoef; p->CPU.MaxDiv = maxdiv; p->CPU.CurrCoef = currcoef; p->CPU.CurrDiv = currdiv; p->CPU.TSCFrequency = tscFrequency; p->CPU.FSBFrequency = fsbFrequency; p->CPU.CPUFrequency = cpuFrequency; // keep formatted with spaces instead of tabs DBG("\n---------------------------------------------\n"); DBG("------------------ CPU INFO -----------------\n"); DBG("---------------------------------------------\n"); DBG("Brand String: %s\n", p->CPU.BrandString); // Processor name (BIOS) DBG("Vendor: 0x%x\n", p->CPU.Vendor); // Vendor ex: GenuineIntel DBG("Family: 0x%x\n", p->CPU.Family); // Family ex: 6 (06h) DBG("ExtFamily: 0x%x\n", p->CPU.ExtFamily); DBG("Signature: %x\n", p->CPU.Signature); // CPUID signature DBG("Model: 0x%x\n", p->CPU.Model); // Model ex: 37 (025h) DBG("ExtModel: 0x%x\n", p->CPU.ExtModel); DBG("Stepping: 0x%x\n", p->CPU.Stepping); // Stepping ex: 5 (05h) DBG("MaxCoef: 0x%x\n", p->CPU.MaxCoef); DBG("CurrCoef: 0x%x\n", p->CPU.CurrCoef); DBG("MaxDiv: 0x%x\n", p->CPU.MaxDiv); DBG("CurrDiv: 0x%x\n", p->CPU.CurrDiv); DBG("TSCFreq: %dMHz\n", p->CPU.TSCFrequency / 1000000); DBG("FSBFreq: %dMHz\n", p->CPU.FSBFrequency / 1000000); DBG("CPUFreq: %dMHz\n", p->CPU.CPUFrequency / 1000000); DBG("Cores: %d\n", p->CPU.NoCores); // Cores DBG("Logical processor: %d\n", p->CPU.NoThreads); // Logical procesor DBG("Features: 0x%08x\n", p->CPU.Features); DBG("\n---------------------------------------------\n"); #if DEBUG_CPU pause(); #endif }
int processBootOptions(void) { char *cp_cache = (char*)(uint32_t)get_env(envgBootArgs); if (cp_cache) { bzero(gBootArgs,sizeof(gBootArgs)); strlcpy(gBootArgs, cp_cache,sizeof(gBootArgs)); } const char * cp = gBootArgs; const char * val = 0; const char * kernel; int cnt; int userCnt; char * argP; char * configKernelFlags; int ArgCntRemaining; skipblanks( &cp ); // Update the unit and partition number. if ( ((BVRef)(uint32_t)get_env(envgBootVolume)) ) { #ifndef NO_MULTIBOOT_SUPPORT if (!( ((BVRef)(uint32_t)get_env(envgBootVolume))->flags & kBVFlagNativeBoot )) { readBootSector( ((BVRef)(uint32_t)get_env(envgBootVolume))->biosdev, ((BVRef)(uint32_t)get_env(envgBootVolume))->part_boff, (void *) 0x7c00 ); // // Setup edx, and signal intention to chain load the // foreign booter. // extern unsigned char chainbootdev; extern unsigned char chainbootflag; chainbootdev = ((BVRef)(uint32_t)get_env(envgBootVolume))->biosdev; chainbootflag = 1; return 1; } #endif setRootVolume(((BVRef)(uint32_t)get_env(envgBootVolume))); } // If no boot volume fail immediately because we're just going to fail // trying to load the config file anyway. else return -1; // Load config table specified by the user, or use the default. if (!getValueForBootKey(cp, "config", &val, &cnt)) { val = 0; cnt = 0; } // Load com.apple.Boot.plist from the selected volume // and use its contents to override default bootConfig. // This is not a mandatory opeartion anymore. loadOverrideConfig(); // Load System com.apple.boot.plist config file loadSystemConfig(); #if virtualM || PCI_FIX // we can simply make an option for this fix addBootArg("npci=0x2000"); #endif #if verbose addBootArg("-v"); #endif // Use the kernel name specified by the user, or fetch the name // in the config table, or use the default if not specified. // Specifying a kernel name on the command line, or specifying // a non-default kernel name in the config file counts as // overriding the kernel, which causes the kernelcache not // to be used. safe_set_env(envgOverrideKernel,false); if (( kernel = extractKernelName((char **)&cp) )) { strlcpy( bootInfo->bootFile, kernel, sizeof(bootInfo->bootFile) ); safe_set_env(envgOverrideKernel,true); } else { if ( getValueForKey( kKernelNameKey, &val, &cnt, DEFAULT_BOOT_CONFIG ) ) { strlcpy( bootInfo->bootFile, val, sizeof(bootInfo->bootFile) ); if (strncmp( bootInfo->bootFile, kDefaultKernel, sizeof(kDefaultKernel) ) != 0) { safe_set_env(envgOverrideKernel,true); } } else if (((BVRef)(uint32_t)get_env(envgBootVolume))->kernelfound == true) { strlcpy( bootInfo->bootFile, kDefaultKernel, sizeof(bootInfo->bootFile) ); } else { printf("No kernel found on this volume : hd(%d,%d)\n", BIOS_DEV_UNIT(((BVRef)(uint32_t)get_env(envgBootVolume))), ((BVRef)(uint32_t)get_env(envgBootVolume))->part_no); sleep(1); return -1; } } ArgCntRemaining = BOOT_STRING_LEN - 2; // save 1 for NULL, 1 for space argP = bootArgs->CommandLine; // Get config table kernel flags, if not ignored. if (getValueForBootKey(cp, kIgnoreBootFileFlag, &val, &cnt) || !getValueForKey( kKernelFlagsKey, &val, &cnt, DEFAULT_BOOT_CONFIG )) { val = ""; cnt = 0; } configKernelFlags = newString(val); { bool isSafeMode = false; if (configKernelFlags) { isSafeMode = getValueForBootKey(configKernelFlags, kSafeModeFlag, &val, &cnt); } if (!getValueForBootKey(cp, kSafeModeFlag, &val, &cnt) && (isSafeMode == false)) { if (get_env(envgBootMode) & kBootModeSafe) { copyArgument(0, kSafeModeFlag, strlen(kSafeModeFlag), &argP, &ArgCntRemaining); } } } if (configKernelFlags) { // Store the merged kernel flags and boot args. cnt = strlen(configKernelFlags); if (cnt) { if (cnt > ArgCntRemaining) { printf("Warning: boot arguments too long, truncating\n"); cnt = ArgCntRemaining; } strncpy(argP, configKernelFlags, cnt); argP[cnt++] = ' '; ArgCntRemaining -= cnt; } } userCnt = strlen(cp); if (userCnt > ArgCntRemaining) { printf("Warning: boot arguments too long, truncating\n"); userCnt = ArgCntRemaining; } strncpy(&argP[cnt], cp, userCnt); argP[cnt+userCnt] = '\0'; if(!get_env(envShouldboot)) { bool gVerboseMode = getValueForKey( kVerboseModeFlag, &val, &cnt, DEFAULT_BOOT_CONFIG ) || getValueForKey( kSingleUserModeFlag, &val, &cnt, DEFAULT_BOOT_CONFIG ); safe_set_env(envgVerboseMode, gVerboseMode); long gBootMode = ( getValueForKey( kSafeModeFlag, &val, &cnt, DEFAULT_BOOT_CONFIG ) ) ? kBootModeSafe : kBootModeNormal; safe_set_env(envgBootMode,gBootMode); if ( getValueForKey( kIgnoreCachesFlag, &val, &cnt, DEFAULT_BOOT_CONFIG ) ) { gBootMode = kBootModeSafe; safe_set_env(envgBootMode,gBootMode); } } if ( getValueForKey( kMKextCacheKey, &val, &cnt, DEFAULT_BOOT_CONFIG ) ) { char * MKextName = (char*)(uint32_t)get_env(envMKextName); strlcpy(MKextName,val,Cache_len_name); } if (configKernelFlags) { free(configKernelFlags); } safe_set_env(envArgCntRemaining,ArgCntRemaining); return 0; }
/** Compute necessary space requirements for new smbios */ static struct SMBEntryPoint *smbios_dry_run(struct SMBEntryPoint *origsmbios) { struct SMBEntryPoint *ret; char *smbiostables; char *tablesptr; int origsmbiosnum; int i, j; int tablespresent[256]; bool do_auto=true; bzero(tablespresent, sizeof(tablespresent)); getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig); ret = (struct SMBEntryPoint *)AllocateKernelMemory(sizeof(struct SMBEntryPoint)); if (origsmbios) { smbiostables = (char *)origsmbios->dmi.tableAddress; origsmbiosnum = origsmbios->dmi.structureCount; } else { smbiostables = NULL; origsmbiosnum = 0; } // _SM_ ret->anchor[0] = 0x5f; ret->anchor[1] = 0x53; ret->anchor[2] = 0x4d; ret->anchor[3] = 0x5f; ret->entryPointLength = sizeof(*ret); ret->majorVersion = 2; ret->minorVersion = 1; ret->maxStructureSize = 0; // will be calculated later in this function ret->entryPointRevision = 0; for (i=0;i<5;i++) { ret->formattedArea[i] = 0; } //_DMI_ ret->dmi.anchor[0] = 0x5f; ret->dmi.anchor[1] = 0x44; ret->dmi.anchor[2] = 0x4d; ret->dmi.anchor[3] = 0x49; ret->dmi.anchor[4] = 0x5f; ret->dmi.tableLength = 0; // will be calculated later in this function ret->dmi.tableAddress = 0; // will be initialized in smbios_real_run() ret->dmi.structureCount = 0; // will be calculated later in this function ret->dmi.bcdRevision = 0x21; tablesptr = smbiostables; // add stringlen of overrides to original stringlen, update maxStructure size adequately, // update structure count and tablepresent[type] with count of type. if (smbiostables) { for (i=0; i<origsmbiosnum; i++) { struct smbios_table_header *cur = (struct smbios_table_header *)tablesptr; char *stringsptr; int stringlen; tablesptr += cur->length; stringsptr = tablesptr; for (; tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++); tablesptr += 2; stringlen = tablesptr - stringsptr - 1; if (stringlen == 1) { stringlen = 0; } for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) { const char *str; int size; char altname[40]; sprintf(altname, "%s_%d",smbios_properties[j].name, tablespresent[cur->type] + 1); if (smbios_properties[j].table_type == cur->type && smbios_properties[j].value_type == SMSTRING && (getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig) || getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig))) { stringlen += size + 1; } else if (smbios_properties[j].table_type == cur->type && smbios_properties[j].value_type == SMSTRING && do_auto && smbios_properties[j].auto_str) { stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[cur->type])) + 1; } } if (stringlen == 0) { stringlen = 1; } stringlen++; if (ret->maxStructureSize < cur->length+stringlen) { ret->maxStructureSize=cur->length+stringlen; } ret->dmi.tableLength += cur->length+stringlen; ret->dmi.structureCount++; tablespresent[cur->type]++; } } // Add eventually table types whose detected count would be < required count, and update ret header with: // new stringlen addons, structure count, and tablepresent[type] count adequately for (i=0; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) { int numnec=-1; char buffer[40]; sprintf(buffer, "SMtable%d", i); if (!getIntForKey(buffer, &numnec, &bootInfo->smbiosConfig)) { numnec = -1; } if (numnec==-1 && do_auto && smbios_table_descriptions[i].numfunc) { numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type); } while (tablespresent[smbios_table_descriptions[i].type] < numnec) { int stringlen = 0; for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) { const char *str; int size; char altname[40]; sprintf(altname, "%s_%d",smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type] + 1); if (smbios_properties[j].table_type == smbios_table_descriptions[i].type && smbios_properties[j].value_type == SMSTRING && (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) || getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))) { stringlen += size + 1; } else if (smbios_properties[j].table_type == smbios_table_descriptions[i].type && smbios_properties[j].value_type==SMSTRING && do_auto && smbios_properties[j].auto_str) { stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type])) + 1; } } if (stringlen == 0) { stringlen = 1; } stringlen++; if (ret->maxStructureSize < smbios_table_descriptions[i].len+stringlen) { ret->maxStructureSize = smbios_table_descriptions[i].len + stringlen; } ret->dmi.tableLength += smbios_table_descriptions[i].len + stringlen; ret->dmi.structureCount++; tablespresent[smbios_table_descriptions[i].type]++; } } return ret; }
//========================================================================== // The 'main' function for the booter. Called by boot0 when booting // from a block device, or by the network booter. // // arguments: // biosdev - Value passed from boot1/NBP to specify the device // that the booter was loaded from. // // If biosdev is kBIOSDevNetwork, then this function will return if // booting was unsuccessful. This allows the PXE firmware to try the // next boot device on its list. void common_boot(int biosdev) { bool quiet; bool firstRun = true; bool instantMenu; bool rescanPrompt; int status; unsigned int allowBVFlags = kBVFlagSystemVolume | kBVFlagForeignBoot; unsigned int denyBVFlags = kBVFlagEFISystem; // Set reminder to unload the PXE base code. Neglect to unload // the base code will result in a hang or kernel panic. gUnloadPXEOnExit = true; // Record the device that the booter was loaded from. gBIOSDev = biosdev & kBIOSDevMask; // Initialize boot info structure. initKernBootStruct(); initBooterLog(); // Setup VGA text mode. // Not sure if it is safe to call setVideoMode() before the // config table has been loaded. Call video_mode() instead. #if DEBUG printf("before video_mode\n"); #endif video_mode( 2 ); // 80x25 mono text mode. #if DEBUG printf("after video_mode\n"); #endif // Scan and record the system's hardware information. scan_platform(); // First get info for boot volume. scanBootVolumes(gBIOSDev, 0); bvChain = getBVChainForBIOSDev(gBIOSDev); setBootGlobals(bvChain); // Load boot.plist config file status = loadChameleonConfig(&bootInfo->chameleonConfig); if (getBoolForKey(kQuietBootKey, &quiet, &bootInfo->chameleonConfig) && quiet) { gBootMode |= kBootModeQuiet; } // Override firstRun to get to the boot menu instantly by setting "Instant Menu"=y in system config if (getBoolForKey(kInstantMenuKey, &instantMenu, &bootInfo->chameleonConfig) && instantMenu) { firstRun = false; } // Loading preboot ramdisk if exists. loadPrebootRAMDisk(); // Disable rescan option by default gEnableCDROMRescan = false; // Enable it with Rescan=y in system config if (getBoolForKey(kRescanKey, &gEnableCDROMRescan, &bootInfo->chameleonConfig) && gEnableCDROMRescan) { gEnableCDROMRescan = true; } // Ask the user for Rescan option by setting "Rescan Prompt"=y in system config. rescanPrompt = false; if (getBoolForKey(kRescanPromptKey, &rescanPrompt , &bootInfo->chameleonConfig) && rescanPrompt && biosDevIsCDROM(gBIOSDev)) { gEnableCDROMRescan = promptForRescanOption(); } // Enable touching a single BIOS device only if "Scan Single Drive"=y is set in system config. if (getBoolForKey(kScanSingleDriveKey, &gScanSingleDrive, &bootInfo->chameleonConfig) && gScanSingleDrive) { gScanSingleDrive = true; } // Create a list of partitions on device(s). if (gScanSingleDrive) { scanBootVolumes(gBIOSDev, &bvCount); } else { scanDisks(gBIOSDev, &bvCount); } // Create a separated bvr chain using the specified filters. bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount); gBootVolume = selectBootVolume(bvChain); // Intialize module system init_module_system(); #if DEBUG printf(" Default: %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBootVolume, gBootVolume->biosdev, gBootVolume->part_no, gBootVolume->flags); printf(" bt(0,0): %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBIOSBootVolume, gBIOSBootVolume->biosdev, gBIOSBootVolume->part_no, gBIOSBootVolume->flags); getchar(); #endif useGUI = true; // Override useGUI default getBoolForKey(kGUIKey, &useGUI, &bootInfo->chameleonConfig); if (useGUI && initGUI()) { // initGUI() returned with an error, disabling GUI. useGUI = false; } setBootGlobals(bvChain); // Parse args, load and start kernel. while (1) { bool tryresume, tryresumedefault, forceresume; bool useKernelCache = true; // by default try to use the prelinked kernel const char *val; int len, ret = -1; long flags, sleeptime, time; void *binary = (void *)kLoadAddr; char bootFile[sizeof(bootInfo->bootFile)]; char bootFilePath[512]; char kernelCacheFile[512]; // Initialize globals. sysConfigValid = false; gErrors = false; status = getBootOptions(firstRun); firstRun = false; if (status == -1) continue; status = processBootOptions(); // Status == 1 means to chainboot if ( status == 1 ) break; // Status == -1 means that the config file couldn't be loaded or that gBootVolume is NULL if ( status == -1 ) { // gBootVolume == NULL usually means the user hit escape. if (gBootVolume == NULL) { freeFilteredBVChain(bvChain); if (gEnableCDROMRescan) rescanBIOSDevice(gBIOSDev); bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount); setBootGlobals(bvChain); setupDeviceList(&bootInfo->themeConfig); } continue; } // Other status (e.g. 0) means that we should proceed with boot. // Turn off any GUI elements if ( bootArgs->Video.v_display == GRAPHICS_MODE ) { gui.devicelist.draw = false; gui.bootprompt.draw = false; gui.menu.draw = false; gui.infobox.draw = false; gui.logo.draw = false; drawBackground(); updateVRAM(); } // Find out which version mac os we're booting. getOSVersion(); if (platformCPUFeature(CPU_FEATURE_EM64T)) { archCpuType = CPU_TYPE_X86_64; } else { archCpuType = CPU_TYPE_I386; } if (getValueForKey(karch, &val, &len, &bootInfo->chameleonConfig)) { if (strncmp(val, "i386", 4) == 0) { archCpuType = CPU_TYPE_I386; } } if (getValueForKey(kKernelArchKey, &val, &len, &bootInfo->chameleonConfig)) { if (strncmp(val, "i386", 4) == 0) { archCpuType = CPU_TYPE_I386; } } // Notify modules that we are attempting to boot execute_hook("PreBoot", NULL, NULL, NULL, NULL); if (!getBoolForKey (kWake, &tryresume, &bootInfo->chameleonConfig)) { tryresume = true; tryresumedefault = true; } else { tryresumedefault = false; } if (!getBoolForKey (kForceWake, &forceresume, &bootInfo->chameleonConfig)) { forceresume = false; } if (forceresume) { tryresume = true; tryresumedefault = false; } while (tryresume) { const char *tmp; BVRef bvr; if (!getValueForKey(kWakeImage, &val, &len, &bootInfo->chameleonConfig)) val = "/private/var/vm/sleepimage"; // Do this first to be sure that root volume is mounted ret = GetFileInfo(0, val, &flags, &sleeptime); if ((bvr = getBootVolumeRef(val, &tmp)) == NULL) break; // Can't check if it was hibernation Wake=y is required if (bvr->modTime == 0 && tryresumedefault) break; if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)) break; if (!forceresume && ((sleeptime+3)<bvr->modTime)) { #if DEBUG printf ("Hibernate image is too old by %d seconds. Use ForceWake=y to override\n", bvr->modTime-sleeptime); #endif break; } HibernateBoot((char *)val); break; } verbose("Loading Darwin %s\n", gMacOSVersion); getBoolForKey(kUseKernelCache, &useKernelCache, &bootInfo->chameleonConfig); if (useKernelCache) do { // Determine the name of the Kernel Cache if (getValueForKey(kKernelCacheKey, &val, &len, &bootInfo->bootConfig)) { if (val[0] == '\\') { len--; val++; } strlcpy(kernelCacheFile, val, len + 1); } else { kernelCacheFile[0] = 0; // Use default kernel cache file } if (gOverrideKernel && kernelCacheFile[0] == 0) { verbose("Using a non default kernel (%s) without specifying 'Kernel Cache' path, KernelCache will not be used\n", bootInfo->bootFile); useKernelCache = false; break; } if (gMKextName[0] != 0) { verbose("Using a specific MKext Cache (%s), KernelCache will not be used\n", gMKextName); useKernelCache = false; break; } if (gBootFileType != kBlockDeviceType) useKernelCache = false; } while(0); do { if (useKernelCache) { ret = LoadKernelCache(kernelCacheFile, &binary); if (ret >= 0) break; } bool bootFileWithDevice = false; // Check if bootFile start with a device ex: bt(0,0)/Extra/mach_kernel if (strncmp(bootInfo->bootFile,"bt(",3) == 0 || strncmp(bootInfo->bootFile,"hd(",3) == 0 || strncmp(bootInfo->bootFile,"rd(",3) == 0) bootFileWithDevice = true; // bootFile must start with a / if it not start with a device name if (!bootFileWithDevice && (bootInfo->bootFile)[0] != '/') sprintf(bootFile, "/%s", bootInfo->bootFile); // append a leading / else strlcpy(bootFile, bootInfo->bootFile, sizeof(bootFile)); // Try to load kernel image from alternate locations on boot helper partitions. ret = -1; if ((gBootVolume->flags & kBVFlagBooter) && !bootFileWithDevice) { sprintf(bootFilePath, "com.apple.boot.P%s", bootFile); ret = GetFileInfo(NULL, bootFilePath, &flags, &time); if (ret == -1) { sprintf(bootFilePath, "com.apple.boot.R%s", bootFile); ret = GetFileInfo(NULL, bootFilePath, &flags, &time); if (ret == -1) { sprintf(bootFilePath, "com.apple.boot.S%s", bootFile); ret = GetFileInfo(NULL, bootFilePath, &flags, &time); } } } if (ret == -1) { // No alternate location found, using the original kernel image path. strlcpy(bootFilePath, bootFile,sizeof(bootFilePath)); } verbose("Loading kernel %s\n", bootFilePath); ret = LoadThinFatFile(bootFilePath, &binary); if (ret <= 0 && archCpuType == CPU_TYPE_X86_64) { archCpuType = CPU_TYPE_I386; ret = LoadThinFatFile(bootFilePath, &binary); } } while (0); clearActivityIndicator(); #if DEBUG printf("Pausing..."); sleep(8); #endif if (ret <= 0) { printf("Can't find %s\n", bootFile); sleep(1); if (gBootFileType == kNetworkDeviceType) { // Return control back to PXE. Don't unload PXE base code. gUnloadPXEOnExit = false; break; } pause(); } else { /* Won't return if successful. */ ret = ExecKernel(binary); } } // chainboot if (status == 1) { // if we are already in graphics-mode, if (getVideoMode() == GRAPHICS_MODE) { setVideoMode(VGA_TEXT_MODE, 0); // switch back to text mode. } } if ((gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit) { nbpUnloadBaseCode(); } }
/* Compute necessary space requirements for new smbios */ struct SMBEntryPoint * smbios_dry_run (struct SMBEntryPoint * origsmbios) { struct SMBEntryPoint *ret; char *smbiostables=0; char *tablesptr; int origsmbiosnum=0; int i, j; int tablespresent[256]; BOOL do_auto=1; getBoolForKey("SMBIOSdefaults",&do_auto,&bootInfo->bootConfig); for (i=0;i<256;i++) tablespresent[i]=0; ret=(struct SMBEntryPoint *)AllocateKernelMemory(sizeof (struct SMBEntryPoint)); if (origsmbios) { smbiostables=(char *)origsmbios->dmi.tableAddress; origsmbiosnum=origsmbios->dmi.structureCount; } // _SM_ ret->anchor[0]=0x5f; ret->anchor[1]=0x53; ret->anchor[2]=0x4d; ret->anchor[3]=0x5f; ret->entryPointLength=sizeof (*ret); ret->majorVersion=2; ret->minorVersion=1; ret->maxStructureSize=0; ret->entryPointRevision=0; for (i=0;i<5;i++) ret->formattedArea[i]=0; //_DMI_ ret->dmi.anchor[0]=0x5f; ret->dmi.anchor[1]=0x44; ret->dmi.anchor[2]=0x4d; ret->dmi.anchor[3]=0x49; ret->dmi.anchor[4]=0x5f; ret->dmi.tableLength=0; ret->dmi.tableAddress=0; ret->dmi.structureCount=0; ret->dmi.bcdRevision=0x21; tablesptr=smbiostables; if (smbiostables) for (i=0;i<origsmbiosnum;i++) { struct smbios_table_header *cur =(struct smbios_table_header *) tablesptr; char *stringsptr; int stringlen; tablesptr+=cur->length; stringsptr=tablesptr; for (;tablesptr[0]!=0 || tablesptr[1]!=0;tablesptr++); tablesptr+=2; stringlen=tablesptr-stringsptr-1; if (stringlen==1) stringlen=0; for (j=0;j<sizeof (smbios_properties)/sizeof(smbios_properties[0]); j++) { const char *str; int size; char altname[40]; sprintf (altname, "%s_%d",smbios_properties[j].name, tablespresent[cur->type]+1); if (smbios_properties[j].table_type==cur->type && smbios_properties[j].value_type==SMSTRING && (getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig) || getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig))) stringlen+=size+1; else if (smbios_properties[j].table_type==cur->type && smbios_properties[j].value_type==SMSTRING && do_auto && smbios_properties[j].auto_str) stringlen+=strlen(smbios_properties[j].auto_str(smbios_properties[j].name,tablespresent[cur->type]))+1; } if (stringlen==0) stringlen=1; stringlen++; if (ret->maxStructureSize<cur->length+stringlen) ret->maxStructureSize=cur->length+stringlen; ret->dmi.tableLength+=cur->length+stringlen; ret->dmi.structureCount++; tablespresent[cur->type]++; } for (i=0;i<sizeof (smbios_table_descriptions) /sizeof(smbios_table_descriptions[0]);i++) { int numnec=-1; char buffer[40]; sprintf (buffer, "SMtable%d", i); if (!getIntForKey(buffer,&numnec,&bootInfo->smbiosConfig)) numnec=-1; if (numnec==-1 && do_auto && smbios_table_descriptions[i].numfunc) numnec=smbios_table_descriptions[i].numfunc (smbios_table_descriptions[i].type); while (tablespresent[smbios_table_descriptions[i].type]<numnec) { int stringlen=0; for (j=0;j<sizeof (smbios_properties)/sizeof(smbios_properties[0]); j++) { const char *str; int size; char altname[40]; sprintf (altname, "%s_%d",smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type]+1); if (smbios_properties[j].table_type ==smbios_table_descriptions[i].type && smbios_properties[j].value_type==SMSTRING && (getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig) || getValueForKey(smbios_properties[j].name,&str, &size, &bootInfo->smbiosConfig))) stringlen+=size+1; else if (smbios_properties[j].table_type ==smbios_table_descriptions[i].type && smbios_properties[j].value_type==SMSTRING && do_auto && smbios_properties[j].auto_str) stringlen+=strlen(smbios_properties[j].auto_str (smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type]))+1; } if (stringlen==0) stringlen=1; stringlen++; if (ret->maxStructureSize<smbios_table_descriptions[i].len+stringlen) ret->maxStructureSize=smbios_table_descriptions[i].len+stringlen; ret->dmi.tableLength+=smbios_table_descriptions[i].len+stringlen; ret->dmi.structureCount++; tablespresent[smbios_table_descriptions[i].type]++; } } return ret; }
void loadThemeValues(config_file_t *theme, bool overide) { unsigned int screen_width = gui.screen.width; unsigned int screen_height = gui.screen.height; unsigned int pixel; int alpha; // transparency level 0 (obligue) - 255 (transparent) uint32_t color; // color value formatted RRGGBB int val, len; const char *string; /* * Parse screen parameters */ if(getColorForKey("screen_bgcolor", &color, theme )) gui.screen.bgcolor = (color & 0x00FFFFFF); if(getIntForKey("screen_textmargin_h", &val, theme)) gui.screen.hborder = MIN( gui.screen.width , val ); if(getIntForKey("screen_textmargin_v", &val, theme)) gui.screen.vborder = MIN( gui.screen.height , val ); /* * Parse background parameters */ if(getDimensionForKey("background_pos_x", &pixel, theme, screen_width , images[iBackground].image->width ) ) gui.background.pos.x = pixel; if(getDimensionForKey("background_pos_y", &pixel, theme, screen_height , images[iBackground].image->height ) ) gui.background.pos.y = pixel; /* * Parse logo parameters */ if(getDimensionForKey("logo_pos_x", &pixel, theme, screen_width , images[iLogo].image->width ) ) gui.logo.pos.x = pixel; if(getDimensionForKey("logo_pos_y", &pixel, theme, screen_height , images[iLogo].image->height ) ) gui.logo.pos.y = pixel; /* * Parse progress bar parameters */ if(getDimensionForKey("progressbar_pos_x", &pixel, theme, screen_width , 0 ) ) gui.progressbar.pos.x = pixel; if(getDimensionForKey("progressbar_pos_y", &pixel, theme, screen_height , 0 ) ) gui.progressbar.pos.y = pixel; /* * Parse countdown text parameters */ if(getDimensionForKey("countdown_pos_x", &pixel, theme, screen_width , 0 ) ) gui.countdown.pos.x = pixel; if(getDimensionForKey("countdown_pos_y", &pixel, theme, screen_height , 0 ) ) gui.countdown.pos.y = pixel; /* * Parse devicelist parameters */ if(getIntForKey("devices_max_visible", &val, theme )) gui.maxdevices = MIN( val, gDeviceCount ); if(getIntForKey("devices_iconspacing", &val, theme )) gui.devicelist.iconspacing = val; // check layout for horizontal or vertical gui.layout = HorizontalLayout; if(getValueForKey( "devices_layout", &string, &len, theme)) { if (!strcmp (string, "vertical")) { gui.layout = VerticalLayout; } } switch (gui.layout) { case VerticalLayout: gui.devicelist.height = ((images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing) * MIN(gui.maxdevices, gDeviceCount) + (images[iDeviceScrollPrev].image->height + images[iDeviceScrollNext].image->height) + gui.devicelist.iconspacing); gui.devicelist.width = (images[iSelection].image->width + gui.devicelist.iconspacing); if(getDimensionForKey("devices_pos_x", &pixel, theme, gui.screen.width , images[iSelection].image->width ) ) gui.devicelist.pos.x = pixel; if(getDimensionForKey("devices_pos_y", &pixel, theme, gui.screen.height , gui.devicelist.height ) ) gui.devicelist.pos.y = pixel; break; case HorizontalLayout: default: gui.devicelist.width = ((images[iSelection].image->width + gui.devicelist.iconspacing) * MIN(gui.maxdevices, gDeviceCount) + (images[iDeviceScrollPrev].image->width + images[iDeviceScrollNext].image->width) + gui.devicelist.iconspacing); gui.devicelist.height = (images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing); if(getDimensionForKey("devices_pos_x", &pixel, theme, gui.screen.width , gui.devicelist.width ) ) gui.devicelist.pos.x = pixel; else gui.devicelist.pos.x = ( gui.screen.width - gui.devicelist.width ) / 2; if(getDimensionForKey("devices_pos_y", &pixel, theme, gui.screen.height , images[iSelection].image->height ) ) gui.devicelist.pos.y = pixel; else gui.devicelist.pos.y = ( gui.screen.height - gui.devicelist.height ) / 2; break; } if(getColorForKey("devices_bgcolor", &color, theme)) gui.devicelist.bgcolor = (color & 0x00FFFFFF); if(getIntForKey("devices_transparency", &alpha, theme)) gui.devicelist.bgcolor = gui.devicelist.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24); /* * Parse infobox parameters */ if(getIntForKey("infobox_width", &val, theme)) gui.infobox.width = MIN( screen_width , val ); if(getIntForKey("infobox_height", &val, theme)) gui.infobox.height = MIN( screen_height , val ); if(getDimensionForKey("infobox_pos_x", &pixel, theme, screen_width , gui.infobox.width ) ) gui.infobox.pos.x = pixel; if(getDimensionForKey("infobox_pos_y", &pixel, theme, screen_height , gui.infobox.height ) ) gui.infobox.pos.y = pixel; if(getIntForKey("infobox_textmargin_h", &val, theme)) gui.infobox.hborder = MIN( gui.infobox.width , val ); if(getIntForKey("infobox_textmargin_v", &val, theme)) gui.infobox.vborder = MIN( gui.infobox.height , val ); if(getColorForKey("infobox_bgcolor", &color, theme)) gui.infobox.bgcolor = (color & 0x00FFFFFF); if(getIntForKey("infobox_transparency", &alpha, theme)) gui.infobox.bgcolor = gui.infobox.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24); /* * Parse menu parameters */ if(getDimensionForKey("menu_width", &pixel, theme, gui.screen.width , 0 ) ) gui.menu.width = pixel; else gui.menu.width = images[iMenuSelection].image->width; if(getDimensionForKey("menu_height", &pixel, theme, gui.screen.height , 0 ) ) gui.menu.height = pixel; else gui.menu.height = (infoMenuItemsCount) * images[iMenuSelection].image->height; if(getDimensionForKey("menu_pos_x", &pixel, theme, screen_width , gui.menu.width ) ) gui.menu.pos.x = pixel; if(getDimensionForKey("menu_pos_y", &pixel, theme, screen_height , gui.menu.height ) ) gui.menu.pos.y = pixel; if(getIntForKey("menu_textmargin_h", &val, theme)) gui.menu.hborder = MIN( gui.menu.width , val ); if(getIntForKey("menu_textmargin_v", &val, theme)) gui.menu.vborder = MIN( gui.menu.height , val ); if(getColorForKey("menu_bgcolor", &color, theme)) gui.menu.bgcolor = (color & 0x00FFFFFF); if(getIntForKey("menu_transparency", &alpha, theme)) gui.menu.bgcolor = gui.menu.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24); /* * Parse bootprompt parameters */ if(getDimensionForKey("bootprompt_width", &pixel, theme, screen_width , 0 ) ) gui.bootprompt.width = pixel; if(getIntForKey("bootprompt_height", &val, theme)) gui.bootprompt.height = MIN( screen_height , val ); if(getDimensionForKey("bootprompt_pos_x", &pixel, theme, screen_width , gui.bootprompt.width ) ) gui.bootprompt.pos.x = pixel; if(getDimensionForKey("bootprompt_pos_y", &pixel, theme, screen_height , gui.bootprompt.height ) ) gui.bootprompt.pos.y = pixel; if(getIntForKey("bootprompt_textmargin_h", &val, theme)) gui.bootprompt.hborder = MIN( gui.bootprompt.width , val ); if(getIntForKey("bootprompt_textmargin_v", &val, theme)) gui.bootprompt.vborder = MIN( gui.bootprompt.height , val ); if(getColorForKey("bootprompt_bgcolor", &color, theme)) gui.bootprompt.bgcolor = (color & 0x00FFFFFF); if(getIntForKey("bootprompt_transparency", &alpha, theme)) gui.bootprompt.bgcolor = gui.bootprompt.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24); if(getColorForKey("font_small_color", &color, theme)) gui.screen.font_small_color = (color & 0x00FFFFFF); if(getColorForKey("font_console_color", &color, theme)) gui.screen.font_console_color = (color & 0x00FFFFFF); }
int processBootOptions() { const char *cp = gBootArgs; const char *val = 0; const char *kernel; int cnt; int userCnt; int cntRemaining; char *argP; char *configKernelFlags; char *valueBuffer; valueBuffer = malloc(VALUE_SIZE); skipblanks( &cp ); // Update the unit and partition number. if ( gBootVolume ) { if (!( gBootVolume->flags & kBVFlagNativeBoot )) { readBootSector( gBootVolume->biosdev, gBootVolume->part_boff, (void *) 0x7c00 ); // // Setup edx, and signal intention to chain load the // foreign booter. // chainbootdev = gBootVolume->biosdev; chainbootflag = 1; return 1; } setRootVolume(gBootVolume); } // If no boot volume fail immediately because we're just going to fail // trying to load the config file anyway. else return -1; // Load config table specified by the user, or use the default. if (!getValueForBootKey(cp, "config", &val, &cnt)) { val = 0; cnt = 0; } // Load com.apple.Boot.plist from the selected volume // and use its contents to override default bootConfig. loadSystemConfig(&bootInfo->bootConfig); loadChameleonConfig(&bootInfo->chameleonConfig); // Use the kernel name specified by the user, or fetch the name // in the config table, or use the default if not specified. // Specifying a kernel name on the command line, or specifying // a non-default kernel name in the config file counts as // overriding the kernel, which causes the kernelcache not // to be used. gOverrideKernel = false; if (( kernel = extractKernelName((char **)&cp) )) { strlcpy( bootInfo->bootFile, kernel, sizeof(bootInfo->bootFile) ); } else { if ( getValueForKey( kKernelNameKey, &val, &cnt, &bootInfo->bootConfig ) ) { strlcpy( bootInfo->bootFile, val, cnt+1 ); } else { strlcpy( bootInfo->bootFile, kDefaultKernel, sizeof(bootInfo->bootFile) ); } } if (strcmp( bootInfo->bootFile, kDefaultKernel ) != 0) { gOverrideKernel = true; } cntRemaining = BOOT_STRING_LEN - 2; // save 1 for NULL, 1 for space argP = bootArgs->CommandLine; // Get config kernel flags, if not ignored. if (getValueForBootKey(cp, kIgnoreBootFileFlag, &val, &cnt) || !getValueForKey( kKernelFlagsKey, &val, &cnt, &bootInfo->bootConfig )) { val = ""; cnt = 0; } configKernelFlags = malloc(cnt + 1); strlcpy(configKernelFlags, val, cnt + 1); // boot-uuid can be set either on the command-line or in the config file if (!processBootArgument(kBootUUIDKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, gBootUUIDString, sizeof(gBootUUIDString))) { // // Try an alternate method for getting the root UUID on boot helper partitions. // if (gBootVolume->flags & kBVFlagBooter) { // Load the configuration store in the boot helper partition if (loadHelperConfig(&bootInfo->helperConfig) == 0) { val = getStringForKey(kHelperRootUUIDKey, &bootInfo->helperConfig); if (val != NULL) strlcpy(gBootUUIDString, val, sizeof(gBootUUIDString)); } } // Try to get the volume uuid string if (!strlen(gBootUUIDString) && gBootVolume->fs_getuuid) gBootVolume->fs_getuuid(gBootVolume, gBootUUIDString); // If we have the volume uuid add it to the commandline arguments if (strlen(gBootUUIDString)) copyArgument(kBootUUIDKey, gBootUUIDString, strlen(gBootUUIDString), &argP, &cntRemaining); } if (!processBootArgument(kRootDeviceKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, gRootDevice, ROOT_DEVICE_SIZE)) { cnt = 0; if ( getValueForKey( kBootDeviceKey, &val, &cnt, &bootInfo->chameleonConfig)) { valueBuffer[0] = '*'; cnt++; strlcpy(valueBuffer + 1, val, cnt); val = valueBuffer; } else { if (strlen(gBootUUIDString)) { val = "*uuid"; cnt = 5; } else { // Don't set "rd=.." if there is no boot device key // and no UUID. val = ""; cnt = 0; } } if (cnt > 0) { copyArgument( kRootDeviceKey, val, cnt, &argP, &cntRemaining); } strlcpy( gRootDevice, val, (cnt + 1)); } /* * Removed. We don't need this anymore. * if (!processBootArgument(kPlatformKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, gPlatformName, sizeof(gCacheNameAdler))) { getPlatformName(gPlatformName); copyArgument(kPlatformKey, gPlatformName, strlen(gPlatformName), &argP, &cntRemaining); } */ if (!getValueForBootKey(cp, kSafeModeFlag, &val, &cnt) && !getValueForBootKey(configKernelFlags, kSafeModeFlag, &val, &cnt)) { if (gBootMode & kBootModeSafe) { copyArgument(0, kSafeModeFlag, strlen(kSafeModeFlag), &argP, &cntRemaining); } } // Store the merged kernel flags and boot args. cnt = strlen(configKernelFlags); if (cnt) { if (cnt > cntRemaining) { error("Warning: boot arguments too long, truncating\n"); cnt = cntRemaining; } strncpy(argP, configKernelFlags, cnt); argP[cnt++] = ' '; cntRemaining -= cnt; } userCnt = strlen(cp); if (userCnt > cntRemaining) { error("Warning: boot arguments too long, truncating\n"); userCnt = cntRemaining; } strncpy(&argP[cnt], cp, userCnt); argP[cnt+userCnt] = '\0'; if(!shouldboot) { gVerboseMode = getValueForKey( kVerboseModeFlag, &val, &cnt, &bootInfo->chameleonConfig ) || getValueForKey( kSingleUserModeFlag, &val, &cnt, &bootInfo->chameleonConfig ); gBootMode = ( getValueForKey( kSafeModeFlag, &val, &cnt, &bootInfo->chameleonConfig ) ) ? kBootModeSafe : kBootModeNormal; if ( getValueForKey( kIgnoreCachesFlag, &val, &cnt, &bootInfo->chameleonConfig ) ) { gBootMode = kBootModeSafe; } } if ( getValueForKey( kMKextCacheKey, &val, &cnt, &bootInfo->bootConfig ) ) strlcpy(gMKextName, val, cnt + 1); else gMKextName[0]=0; free(configKernelFlags); free(valueBuffer); return 0; }
//========================================================================== // The 'main' function for the booter. Called by boot0 when booting // from a block device, or by the network booter. // // arguments: // biosdev - Value passed from boot1/NBP to specify the device // that the booter was loaded from. // // If biosdev is kBIOSDevNetwork, then this function will return if // booting was unsuccessful. This allows the PXE firmware to try the // next boot device on its list. void common_boot(int biosdev) { int status; char *bootFile; unsigned long adler32; bool quiet; bool firstRun = true; bool instantMenu; bool rescanPrompt = false; unsigned int allowBVFlags = kBVFlagSystemVolume|kBVFlagForeignBoot; unsigned int denyBVFlags = kBVFlagEFISystem; // Set reminder to unload the PXE base code. Neglect to unload // the base code will result in a hang or kernel panic. gUnloadPXEOnExit = true; // Record the device that the booter was loaded from. gBIOSDev = biosdev & kBIOSDevMask; // Initialize boot info structure. initKernBootStruct(); initBooterLog(); // Setup VGA text mode. // Not sure if it is safe to call setVideoMode() before the // config table has been loaded. Call video_mode() instead. #if DEBUG printf("before video_mode\n"); //Azi: this one is not printing... i remember it did.. check trunk. #endif video_mode( 2 ); // 80x25 mono text mode. #if DEBUG printf("after video_mode\n"); #endif // Scan and record the system's hardware information. scan_platform(); // First get info for boot volume. scanBootVolumes(gBIOSDev, 0); bvChain = getBVChainForBIOSDev(gBIOSDev); //Azi: initialising gBIOSBootVolume & gBootVolume (Startup volume) for the first time.. i think!? // also, kDefaultPartitionKey is checked here, on selectBootVolume. setBootGlobals(bvChain); msglog("setBootGlobals:\n Default: %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBootVolume, gBootVolume->biosdev, gBootVolume->part_no, gBootVolume->flags); msglog(" bt(0,0): %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBIOSBootVolume, gBIOSBootVolume->biosdev, gBIOSBootVolume->part_no, gBIOSBootVolume->flags); // Boot Volume is set as Root at this point so, pointing to Extra, /Extra or bt(0,0)/Extra // is exactly the same. Review bt(0,0)/bla bla paths...... (Reviewing...) //Azi: works as expected but... trying this because Kernel=mach_kernel doesn't work on a // override Boot.plist; this makes it impossible to override e.g. Kernel=bt(0,0)mach_kernel // on the main Boot.plist, when loading kernel from ramdisk btAliased. loadPrebootRAMDisk(); // Load boot.plist config file //Azi: on this first check, boot.plist acts as both "booter config file" // and bootargs/options "carrier".***** status = loadSystemConfig(&bootInfo->bootConfig); if (getBoolForKey(kQuietBootKey, &quiet, &bootInfo->bootConfig) && quiet) { gBootMode |= kBootModeQuiet; } // Override firstRun to get to the boot menu instantly by setting "Instant Menu"=y in system config if (getBoolForKey(kInstantMenuKey, &instantMenu, &bootInfo->bootConfig) && instantMenu) { firstRun = false; } // Loading preboot ramdisk if exists. // loadPrebootRAMDisk(); //Azi: this needs to be done before load_all_modules() // because of btAlias... (Reviewing...) // Intialize module system if (init_module_system()) { load_all_modules(); } // Disable rescan option by default gEnableCDROMRescan = false; // If we're loading the booter from optical media... (Reviewing...) if (biosDevIsCDROM(gBIOSDev)) { // ... ask the user for Rescan option by setting "Rescan Prompt"=y in system config... if (getBoolForKey(kRescanPromptKey, &rescanPrompt, &bootInfo->bootConfig) && rescanPrompt) { gEnableCDROMRescan = promptForRescanOption(); } else // ... or enable it with Rescan=y in system config. if (getBoolForKey(kRescanKey, &gEnableCDROMRescan, &bootInfo->bootConfig) && gEnableCDROMRescan) { gEnableCDROMRescan = true; } } //Azi: Is this a cdrom only thing? (Reviewing...) // Enable touching a single BIOS device only if "Scan Single Drive"=y is set in system config. if (getBoolForKey(kScanSingleDriveKey, &gScanSingleDrive, &bootInfo->bootConfig) && gScanSingleDrive) { scanBootVolumes(gBIOSDev, &bvCount); } else { //Azi: scanDisks uses scanBootVolumes. scanDisks(gBIOSDev, &bvCount); } // Create a separated bvr chain using the specified filters. bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount); gBootVolume = selectBootVolume(bvChain); //#if DEBUG //printf msglog(":something...???\n Default: %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBootVolume, gBootVolume->biosdev, gBootVolume->part_no, gBootVolume->flags); msglog(" bt(0,0): %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBIOSBootVolume, gBIOSBootVolume->biosdev, gBIOSBootVolume->part_no, gBIOSBootVolume->flags); // getchar(); //#endif useGUI = true; // Override useGUI default getBoolForKey(kGUIKey, &useGUI, &bootInfo->bootConfig); // AutoResolution - Azi: default to false // http://forum.voodooprojects.org/index.php/topic,1227.0.html gAutoResolution = false; // Check if user enabled AutoResolution on Boot.plist... getBoolForKey(kAutoResolutionKey, &gAutoResolution, &bootInfo->bootConfig); // Patch the Video Bios with the extracted resolution, before initGui. if (gAutoResolution == true) { initAutoRes(); } if (useGUI && initGUI()) { // initGUI() returned with an error, disabling GUI. useGUI = false; } setBootGlobals(bvChain); msglog("setBootGlobals:\n Default: %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBootVolume, gBootVolume->biosdev, gBootVolume->part_no, gBootVolume->flags); msglog(" bt(0,0): %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBIOSBootVolume, gBIOSBootVolume->biosdev, gBIOSBootVolume->part_no, gBIOSBootVolume->flags); // Parse args, load and start kernel. while (1) { const char *val; int len; int trycache; long flags, cachetime, kerneltime, exttime, sleeptime, time; int ret = -1; void *binary = (void *)kLoadAddr; bool tryresume; bool tryresumedefault; bool forceresume; bool ignoreKC = false; // additional variable for testing alternate kernel image locations on boot helper partitions. char bootFileSpec[512]; // Initialize globals. sysConfigValid = false; gErrors = false; status = getBootOptions(firstRun); firstRun = false; if (status == -1) continue; //Azi: test (gBootVolume == NULL) - so far Ok! // test with optical media again...? // Turn off any GUI elements, draw background and update VRAM. if ( bootArgs->Video.v_display == GRAPHICS_MODE ) { gui.devicelist.draw = false; gui.bootprompt.draw = false; gui.menu.draw = false; gui.infobox.draw = false; gui.logo.draw = false; drawBackground(); updateVRAM(); } status = processBootOptions(); //Azi: AutoResolution - closing Vbios here without restoring, causes an allocation error, // if the user tries to boot, after a e.g."Can't find bla_kernel" msg. // Doing it on execKernel() instead. // Status == 1 means to chainboot if ( status == 1 ) break; // Status == -1 means that gBootVolume is NULL. Config file is not mandatory anymore! if ( status == -1 ) { // gBootVolume == NULL usually means the user hit escape. (Reviewing...) if (gBootVolume == NULL) { freeFilteredBVChain(bvChain); if (gEnableCDROMRescan) rescanBIOSDevice(gBIOSDev); bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount); setBootGlobals(bvChain); setupDeviceList(&bootInfo->themeConfig); } continue; } // Other status (e.g. 0) means that we should proceed with boot. // If cpu handles 64 bit instructions... if (platformCPUFeature(CPU_FEATURE_EM64T)) { // use x86_64 kernel arch,... archCpuType = CPU_TYPE_X86_64; } else { // else use i386 kernel arch. archCpuType = CPU_TYPE_I386; } // If user override... if (getValueForKey(kArchKey, &val, &len, &bootInfo->bootConfig)) { // matches i386... if (strncmp(val, "i386", 4) == 0) { // use i386 kernel arch. archCpuType = CPU_TYPE_I386; } } if (!getBoolForKey (kWakeKey, &tryresume, &bootInfo->bootConfig)) { tryresume = true; tryresumedefault = true; } else { tryresumedefault = false; } if (!getBoolForKey (kForceWakeKey, &forceresume, &bootInfo->bootConfig)) { forceresume = false; } if (forceresume) { tryresume = true; tryresumedefault = false; } while (tryresume) { const char *tmp; BVRef bvr; if (!getValueForKey(kWakeKeyImageKey, &val, &len, &bootInfo->bootConfig)) val="/private/var/vm/sleepimage"; // Do this first to be sure that root volume is mounted ret = GetFileInfo(0, val, &flags, &sleeptime); if ((bvr = getBootVolumeRef(val, &tmp)) == NULL) break; // Can't check if it was hibernation Wake=y is required if (bvr->modTime == 0 && tryresumedefault) break; if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)) break; if (!forceresume && ((sleeptime+3)<bvr->modTime)) { //Azi: no need for printf at this point - reminder printf ("Hibernate image is too old by %d seconds. Use ForceWake=y to override.\n",bvr->modTime-sleeptime); break; } HibernateBoot((char *)val); break; } //Azi:kernelcache stuff bool patchKernel = false; getBoolForKey(kKPatcherKey, &patchKernel, &bootInfo->bootConfig); //Azi: avoiding having to use -f to ignore kernel cache //Azi: ignore kernel cache but still use kext cache (E/E.mkext & S/L/E.mkext). - explain... getBoolForKey(kUseKCKey, &ignoreKC, &bootInfo->bootConfig); // equivalent to UseKernelCache if (ignoreKC) { verbose("KC: cache ignored by user.\n"); // make sure the damn thing get's zeroed, just in case... :)* bzero(gBootKernelCacheFile, sizeof(gBootKernelCacheFile)); } else if (patchKernel) // to be moved..? { verbose("KC: kernel patcher enabled, ignore cache.\n"); bzero(gBootKernelCacheFile, sizeof(gBootKernelCacheFile)); } else if (getValueForKey(kKernelCacheKey, &val, &len, &bootInfo->bootConfig)) { strlcpy(gBootKernelCacheFile, val, len + 1); verbose("KC: path set by user = %s\n", gBootKernelCacheFile); //Azi: bypass time check when user sets path ??? // cache is still ignored if time doesn't match... (e.g. booter on usb stick) } else { // Reset cache name. bzero(gCacheNameAdler + 64, sizeof(gCacheNameAdler) - 64); // kextcache_main.c: Construct entry from UUID of boot volume...(reminder) // assemble ?string? to generate adler from... // sprintf(gCacheNameAdler + 64, "%s,%s", gRootDevice, bootInfo->bootFile); - OLD const char *ProductName = getStringForKey("SMproductname", &bootInfo->smbiosConfig); sprintf(gCacheNameAdler, ProductName); // well, at least the smbios.plist can be loaded this early... // to set/get "ProductName" this early, booter needs complete rewrite!! // see DHP's Revolution booter rework example! // verbose("KC: gCacheNameAdler 1 = %s\n", gCacheNameAdler); //Azi: check the validity of this, e.g. on Helper Partitions sprintf(gCacheNameAdler + 64, "%s", "\\System\\Library\\CoreServices\\boot.efi"); // verbose("KC: gCacheNameAdler 2 = %s\n", gCacheNameAdler + 64); sprintf(gCacheNameAdler + (64 + 38), "%s", bootInfo->bootFile); // verbose("KC: gCacheNameAdler 3 = %s\n", gCacheNameAdler + (64 + 38)); // generate adler adler32 = Adler32((unsigned char *)gCacheNameAdler, sizeof(gCacheNameAdler)); // verbose("KC: Adler32 = %08X\n", adler32); //Azi: no check for OS version here ?? - yes there is :) // append arch and/or adler (checksum) to kc path... if (gMacOSVersion[3] <= '5') { sprintf(gBootKernelCacheFile, "%s.%08lX", kCachePathTigerLeopard, adler32); // verbose("KC: adler added to path = %s\n", gBootKernelCacheFile); } else { sprintf(gBootKernelCacheFile, "%s_%s.%08X", kCachePathSnowLion, (archCpuType == CPU_TYPE_I386) ? "i386" : "x86_64", adler32); // verbose("KC: arch & adler added to path = %s\n", gBootKernelCacheFile); } } // Check for cache file. //Azi: trycache is done if... trycache = ( ( (gBootMode & kBootModeSafe) == 0) //... we're not booting in safe mode (-x arg), && !gOverrideKernel // we're not overriding default kernel "name", && (gBootFileType == kBlockDeviceType) // we're booting from local storage device, && (gMKextName[0] == '\0') // "MKext Cache" key IS NOT in use, and && (gBootKernelCacheFile[0] != '\0') ); // gBootKernelCacheFile is populated. // we could add the use of "kernelpatcher" to this bunch..?? // verbose("Loading Darwin %s\n", gMacOSVersion); //Azi: move?? to getOSVersion? :) if (trycache) do { verbose("KC: checking kernel cache (system prelinked kernel)...\n"); // if we haven't found the kernel yet, don't use the cache ret = GetFileInfo(NULL, bootInfo->bootFile, &flags, &kerneltime); if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)) { verbose("KC: no kernel found (shouldn't happen?!?)\n"); trycache = 0; // ignore kernel cache... break; } verbose("KC: kerneltime = %d\n", kerneltime); ret = GetFileInfo(NULL, gBootKernelCacheFile, &flags, &cachetime); if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat) || (cachetime < kerneltime)) { if (cachetime <= 100) // confirm: 100 = inexistent path, -xxxxxxxxx = wrong name // not confirming... i also get -xxxxxxxxx with inexisting prelinked kernel verbose("KC: cachetime = %d, kernel cache path/adler is incorrect, ignoring it. ??? \n", cachetime); else verbose("KC: cachetime = %d, kernel cache is older than the kernel, ignoring it.\n", cachetime); trycache = 0; break; } verbose("KC: cachetime = %d\n", cachetime); ret = GetFileInfo("/System/Library/", "Extensions", &flags, &exttime); if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory) && (cachetime < exttime)) { verbose("KC: exttime = %d, kernel cache is older than S/L/E, ignoring it.\n", exttime); trycache = 0; break; } verbose("KC: exttime = %d\n", exttime); if (kerneltime > exttime) // if S/L/E is older than the kernel... { verbose("KC: S/L/E is older than the kernel, matching exttime with kerneltime...\n"); exttime = kerneltime; } verbose("KC: exttime +1 = %d\n", exttime + 1); if (cachetime != (exttime + 1)) { verbose("KC: kernel cache time is diff from S/L/E time, ignoring it.\n"); trycache = 0; break; } verbose("KC: kernel cache found and up to date, will be used.\n"); } while (0); do { // Load kernel cache if not ignored. if (trycache) { bootFile = gBootKernelCacheFile; verbose("Loading kernel cache %s\n", bootFile); ret = LoadFile(bootFile); binary = (void *)kLoadAddr; if (ret >= 0) { break; } } bootFile = bootInfo->bootFile; // Try to load kernel image from alternate locations on boot helper partitions. sprintf(bootFileSpec, "com.apple.boot.P/%s", bootFile); ret = GetFileInfo(NULL, bootFileSpec, &flags, &time); if (ret == -1) { sprintf(bootFileSpec, "com.apple.boot.R/%s", bootFile); ret = GetFileInfo(NULL, bootFileSpec, &flags, &time); if (ret == -1) { sprintf(bootFileSpec, "com.apple.boot.S/%s", bootFile); ret = GetFileInfo(NULL, bootFileSpec, &flags, &time); if (ret == -1) { // No alternate location found, using the original kernel image path. strcpy(bootFileSpec, bootFile); } } } verbose("Loading kernel %s\n", bootFileSpec); ret = LoadThinFatFile(bootFileSpec, &binary); if (ret <= 0 && archCpuType == CPU_TYPE_X86_64) { archCpuType = CPU_TYPE_I386; ret = LoadThinFatFile(bootFileSpec, &binary); } } while (0); clearActivityIndicator(); /*#if DEBUG printf("Pausing..."); sleep(8); #endif Azi: annoying stuff :P */ if (ret <= 0) { printf("Can't find %s\n", bootFile); sleep(1); if (gBootFileType == kNetworkDeviceType) { // Return control back to PXE. Don't unload PXE base code. gUnloadPXEOnExit = false; break; } } else { // Won't return if successful. ret = ExecKernel(binary); } } // while (1) // chainboot if (status==1) { if (getVideoMode() == GRAPHICS_MODE) { // if we are already in graphics-mode, setVideoMode(VGA_TEXT_MODE, 0); // switch back to text mode } } if ((gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit) { nbpUnloadBaseCode(); } }