/* * Initialize the module system by loading the Symbols.dylib module. * Once loaded, locate the _lookup_symbol function so that internal * symbols can be resolved. */ int init_module_system() { // Start any modules that were compiled in first. start_built_in_modules(); int retVal = 0; void (*module_start)(void) = NULL; char* module_data = symbols_module_start + BOOT2_ADDR; // Intialize module system if(symbols_module_start != (void*)0xFFFFFFFF) { // Module system was compiled in (Symbols.dylib addr known) module_start = parse_mach(module_data, &load_module, &add_symbol, NULL); if(module_start && module_start != (void*)0xFFFFFFFF) { // Notify the system that it was laoded module_loaded(SYMBOLS_MODULE, SYMBOLS_AUTHOR, SYMBOLS_DESCRIPTION, SYMBOLS_VERSION, SYMBOLS_COMPAT); (*module_start)(); // Start the module. This will point to load_all_modules due to the way the dylib was constructed. execute_hook("ModulesLoaded", NULL, NULL, NULL, NULL); DBG("Module %s Loaded.\n", SYMBOLS_MODULE); retVal = 1; } else { module_data -= 0x10; // XCODE 4 HACK module_start = parse_mach(module_data, &load_module, &add_symbol, NULL); if(module_start && module_start != (void*)0xFFFFFFFF) { // Notify the system that it was laoded module_loaded(SYMBOLS_MODULE, SYMBOLS_AUTHOR, SYMBOLS_DESCRIPTION, SYMBOLS_VERSION, SYMBOLS_COMPAT); (*module_start)(); // Start the module. This will point to load_all_modules due to the way the dylib was constructed. execute_hook("ModulesLoaded", NULL, NULL, NULL, NULL); DBG("Module %s Loaded.\n", SYMBOLS_MODULE); retVal = 1; } else { // The module does not have a valid start function printf("Unable to start %s\n", SYMBOLS_MODULE); getchar(); } } } return retVal; }
/** scan mem for memory autodection purpose */ void scan_mem() { static bool done = false; if (done) return; execute_hook("ScanMemory", NULL, NULL, NULL, NULL); done = true; }
static void clearBootArgs(void) { gBootArgsPtr = gBootArgs; memset(gBootArgs, '\0', BOOT_STRING_LEN); if (bootArgs->Video.v_display != VGA_TEXT_MODE) { clearGraphicBootPrompt(); } execute_hook("ClearArgs", NULL, NULL, NULL, NULL); }
long LoadDriverMKext( char * fileSpec ) { unsigned long driversAddr, driversLength; long length; char segName[32]; DriversPackage * package; #define GetPackageElement(e) OSSwapBigToHostInt32(package->e) // Load the MKext. length = LoadThinFatFile(fileSpec, (void **)&package); if (length < sizeof (DriversPackage)) { return -1; } // call hook to notify modules that the mkext has been loaded execute_hook("LoadDriverMKext", (void*)fileSpec, (void*)package, (void*) &length, NULL); // Verify the MKext. if (( GetPackageElement(signature1) != kDriverPackageSignature1) || ( GetPackageElement(signature2) != kDriverPackageSignature2) || ( GetPackageElement(length) > kLoadSize ) || ( GetPackageElement(adler32) != Adler32((unsigned char *)&package->version, GetPackageElement(length) - 0x10) ) ) { return -1; } // Make space for the MKext. driversLength = GetPackageElement(length); driversAddr = AllocateKernelMemory(driversLength); // Copy the MKext. memcpy((void *)driversAddr, (void *)package, driversLength); // Add the MKext to the memory map. snprintf(segName, sizeof(segName), "DriversPackage-%lx", driversAddr); AllocateMemoryRange(segName, driversAddr, driversLength, kBootDriverTypeMKEXT); return 0; }
void setup_pci_devs(pci_dt_t *pci_dt) { char *devicepath; bool do_eth_devprop, do_gfx_devprop, do_enable_hpet, do_igp_devprop; pci_dt_t *current = pci_dt; do_eth_devprop = do_gfx_devprop = do_enable_hpet = false; getBoolForKey(kEthernetBuiltIn, &do_eth_devprop, &bootInfo->chameleonConfig); getBoolForKey(kGraphicsEnabler, &do_gfx_devprop, &bootInfo->chameleonConfig); getBoolForKey(kIGPEnabler, &do_igp_devprop, &bootInfo->chameleonConfig); getBoolForKey(kForceHPET, &do_enable_hpet, &bootInfo->chameleonConfig); while (current) { devicepath = get_pci_dev_path(current); switch (current->class_id) { case PCI_CLASS_BRIDGE_HOST: if (current->dev.addr == PCIADDR(0, 0, 0)) dram_controller_dev = current; break; case PCI_CLASS_NETWORK_ETHERNET: if (do_eth_devprop) set_eth_builtin(current); break; case PCI_CLASS_DISPLAY_VGA: if (do_gfx_devprop){ switch (current->vendor_id) { case PCI_VENDOR_ID_ATI: setup_ati_devprop(current); break; case PCI_VENDOR_ID_INTEL: setup_gma_devprop(current); break; case PCI_VENDOR_ID_NVIDIA: setup_nvidia_devprop(current); break; } break; } else if (do_igp_devprop){ setup_gma_devprop(current); break; } case PCI_CLASS_SERIAL_USB: notify_usb_dev(current); break; case PCI_CLASS_BRIDGE_ISA: if (do_enable_hpet) force_enable_hpet(current); break; } execute_hook("PCIDevice", current, NULL, NULL, NULL); setup_pci_devs(current->children); current = current->next; } }
//========================================================================== // 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-log initBooterLog(); // 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 // 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, bvChain); 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; } 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++; } /* FIXME: check len vs sizeof(kernelCacheFile) */ strlcpy(kernelCacheFile, val, len + 1); } else { kernelCacheFile[0] = 0; // Use default kernel cache file } if (gOverrideKernel && kernelCacheFile[0] == 0) { DBG("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) { DBG("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] != '/') { snprintf(bootFile, sizeof(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) { snprintf(bootFilePath, sizeof(bootFilePath), "com.apple.boot.P%s", bootFile); ret = GetFileInfo(NULL, bootFilePath, &flags, &time); if (ret == -1) { snprintf(bootFilePath, sizeof(bootFilePath), "com.apple.boot.R%s", bootFile); ret = GetFileInfo(NULL, bootFilePath, &flags, &time); if (ret == -1) { snprintf(bootFilePath, sizeof(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)); } DBG("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(); } }
long NBI_LoadDrivers( char * dirSpec ) { char dirSpecExtra[1024]; if ( InitDriverSupport() != 0 ) return 0; int step = 0; execute_hook("ramDiskLoadDrivers", &step, NULL, NULL, NULL, NULL, NULL); #ifdef NBP_SUPPORT if ( get_env(envgBootFileType) == kNetworkDeviceType ) { if (NetLoadDrivers(dirSpec) != 0) { error("Could not load drivers from the network\n"); return -1; } } else #endif if ( get_env(envgBootFileType) == kBlockDeviceType ) { verbose("Loading Recovery Extensions\n"); strlcpy(dirSpecExtra, "/Extra/RecoveryExtensions/", sizeof(dirSpecExtra)); FileLoadDrivers(dirSpecExtra, sizeof(dirSpecExtra), 0); #ifdef BOOT_HELPER_SUPPORT // TODO: fix this, the order does matter, and it's not correct now. // Also try to load Extensions from boot helper partitions. if (((BVRef)(uint32_t)get_env(envgBootVolume))->flags & kBVFlagBooter) { strlcpy(dirSpecExtra, "/com.apple.boot.P/System/Library/", sizeof(dirSpecExtra)); if (FileLoadDrivers(dirSpecExtra, sizeof(dirSpecExtra), 0) != 0) { strlcpy(dirSpecExtra, "/com.apple.boot.R/System/Library/", sizeof(dirSpecExtra)); if (FileLoadDrivers(dirSpecExtra, sizeof(dirSpecExtra), 0) != 0) { strlcpy(dirSpecExtra, "/com.apple.boot.S/System/Library/", sizeof(dirSpecExtra)); FileLoadDrivers(dirSpecExtra, sizeof(dirSpecExtra), 0); } } } #endif char * MKextName = (char*)(uint32_t)get_env(envMKextName); if (MKextName[0] != '\0') { verbose("LoadDrivers: Loading from [%s]\n", MKextName); if ( LoadDriverMKext(MKextName) != 0 ) { error("Could not load %s\n", MKextName); return -1; } } else { char * ExtensionsSpec = (char*)(uint32_t)get_env(envDriverExtSpec); strlcpy(ExtensionsSpec, dirSpec, DEFAULT_DRIVER_SPEC_SIZE); strlcat(ExtensionsSpec, "System/Library/", DEFAULT_DRIVER_SPEC_SIZE); FileLoadDrivers(ExtensionsSpec,DEFAULT_DRIVER_SPEC_SIZE, 0); } } else { return 0; } #if UNUSED MatchPersonalities(); #endif MatchLibraries(); LoadMatchedModules(); return 0; }
void setup_pci_devs(pci_dt_t *pci_dt) { char *devicepath; bool do_gfx_devprop = false; bool do_skip_n_devprop = false; bool do_skip_a_devprop = false; bool do_skip_i_devprop = false; bool do_enable_hpet = false; bool do_hda_devprop = false; pci_dt_t *current = pci_dt; // GraphicsEnabler getBoolForKey(kGraphicsEnabler, &do_gfx_devprop, &bootInfo->chameleonConfig); // Skip keys getBoolForKey(kSkipNvidiaGfx, &do_skip_n_devprop, &bootInfo->chameleonConfig); getBoolForKey(kSkipAtiGfx, &do_skip_a_devprop, &bootInfo->chameleonConfig); getBoolForKey(kSkipIntelGfx, &do_skip_i_devprop, &bootInfo->chameleonConfig); // HDAEnable getBoolForKey(kHDAEnabler, &do_hda_devprop, &bootInfo->chameleonConfig); // ForceHPET getBoolForKey(kForceHPET, &do_enable_hpet, &bootInfo->chameleonConfig); while (current) { devicepath = get_pci_dev_path(current); switch (current->class_id) { case PCI_CLASS_BRIDGE_HOST: DBG("Setup BRIDGE_HOST \n"); if (current->dev.addr == PCIADDR(0, 0, 0)) { dram_controller_dev = current; } break; // PCI_CLASS_BRIDGE_HOST case PCI_CLASS_NETWORK_ETHERNET: DBG("Setup ETHERNET %s enabled\n", do_eth_devprop? "is":"is not"); verbose("[ ETHERNET DEVICE INFO ]\n"); setup_eth_devdrop(current); verbose("\n"); break; // PCI_CLASS_NETWORK_ETHERNET case PCI_CLASS_NETWORK_OTHER: DBG("Setup WIRELESS %s enabled\n", do_wifi_devprop? "is":"is not"); verbose("[ WIRELESS DEVICE INFO ]\n"); setup_wifi_devdrop(current); verbose("\n"); break; // PCI_CLASS_NETWORK_OTHER case PCI_CLASS_DISPLAY_VGA: DBG("GraphicsEnabler %s enabled\n", do_gfx_devprop? "is":"is not"); if (do_gfx_devprop) { switch (current->vendor_id) { case PCI_VENDOR_ID_ATI: if ( do_skip_a_devprop ) { verbose("Skip ATi/AMD gfx device!\n"); } else { verbose("[ ATi GFX DEVICE INFO ]\n"); setup_ati_devprop(current); verbose("\n"); } break; // PCI_VENDOR_ID_ATI case PCI_VENDOR_ID_INTEL: if ( do_skip_i_devprop ) { verbose("Skip Intel gfx device!\n"); } else { verbose("[ INTEL GMA DEVICE INFO ]\n"); setup_gma_devprop(current); verbose("\n"); } break; // PCI_VENDOR_ID_INTEL case PCI_VENDOR_ID_NVIDIA: if ( do_skip_n_devprop ) { verbose("Skip Nvidia gfx device!\n"); } else { verbose("[ NVIDIA GFX DEVICE INFO ]\n"); setup_nvidia_devprop(current); verbose("\n"); } break; // PCI_VENDOR_ID_NVIDIA default: break; } } break; // PCI_CLASS_DISPLAY_VGA case PCI_CLASS_MULTIMEDIA_AUDIO_DEV: DBG("Setup HDEF %s enabled\n", do_hda_devprop ? "is":"is not"); if (do_hda_devprop) { verbose("[ AUDIO DEVICE INFO ]\n"); setup_hda_devprop(current); verbose("\n"); } break; // PCI_CLASS_MULTIMEDIA_AUDIO_DEV case PCI_CLASS_SERIAL_USB: DBG("USB\n"); notify_usb_dev(current); break; // PCI_CLASS_SERIAL_USB case PCI_CLASS_SERIAL_FIREWIRE: DBG("FireWire\n"); verbose("[ FIREWIRE DEVICE INFO ]\n"); verbose("\tClass code: [%04X]\n\tFireWire device [%04x:%04x]-[%04x:%04x]\n\t%s\n", current->class_id,current->vendor_id, current->device_id, current->subsys_id.subsys.vendor_id, current->subsys_id.subsys.device_id, devicepath); // set_fwr_devdrop(current); verbose("\n"); break; // PCI_CLASS_SERIAL_FIREWIRE case PCI_CLASS_BRIDGE_ISA: DBG("Force HPET %s enabled\n", do_enable_hpet ? "is":"is not"); if (do_enable_hpet) { verbose("[ HPET ]\n"); force_enable_hpet(current); verbose("\n"); } break; // PCI_CLASS_BRIDGE_ISA } execute_hook("PCIDevice", current, NULL, NULL, NULL); DBG("setup_pci_devs current device ID = [%04x:%04x]\n", current->vendor_id, current->device_id); setup_pci_devs(current->children); current = current->next; } }
static int ExecKernel(void *binary) { int ret; entry_t kernelEntry; bootArgs->kaddr = bootArgs->ksize = 0; execute_hook("ExecKernel", (void*)binary, NULL, NULL, NULL); ret = DecodeKernel(binary, &kernelEntry, (char **) &bootArgs->kaddr, (int *)&bootArgs->ksize ); if ( ret != 0 ) return ret; // Reserve space for boot args reserveKernBootStruct(); // Notify modules that the kernel has been decoded execute_hook("DecodedKernel", (void*)binary, (void*)bootArgs->kaddr, (void*)bootArgs->ksize, NULL); setupFakeEfi(); // Load boot drivers from the specifed root path. //if (!gHaveKernelCache) LoadDrivers("/"); execute_hook("DriversLoaded", (void*)binary, NULL, NULL, NULL); clearActivityIndicator(); if (gErrors) { printf("Errors encountered while starting up the computer.\n"); printf("Pausing %d seconds...\n", kBootErrorTimeout); sleep(kBootErrorTimeout); } md0Ramdisk(); // Cleanup the PXE base code. if ( (gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit ) { if ( (ret = nbpUnloadBaseCode()) != nbpStatusSuccess ) { printf("nbpUnloadBaseCode error %d\n", (int) ret); sleep(2); } } bool dummyVal; if (getBoolForKey(kWaitForKeypressKey, &dummyVal, &bootInfo->chameleonConfig) && dummyVal) { showTextBuffer(msgbuf, strlen(msgbuf)); } usb_loop(); // If we were in text mode, switch to graphics mode. // This will draw the boot graphics unless we are in // verbose mode. if (gVerboseMode) { setVideoMode( GRAPHICS_MODE, 0 ); } else { drawBootGraphics(); } DBG("Starting Darwin/%s [%s]\n",( archCpuType == CPU_TYPE_I386 ) ? "x86" : "x86_64", gDarwinBuildVerStr); DBG("Boot Args: %s\n", bootArgs->CommandLine); setupBooterLog(); finalizeBootStruct(); // Jump to kernel's entry point. There's no going back now. if ((checkOSVersion("10.7")) || (checkOSVersion("10.8")) || (checkOSVersion("10.9"))) { // Notify modules that the kernel is about to be started execute_hook("Kernel Start", (void*)kernelEntry, (void*)bootArgs, NULL, NULL); // Masking out so that Lion doesn't doublefault outb(0x21, 0xff); /* Maskout all interrupts Pic1 */ outb(0xa1, 0xff); /* Maskout all interrupts Pic2 */ startprog( kernelEntry, bootArgs ); } else { // Notify modules that the kernel is about to be started execute_hook("Kernel Start", (void*)kernelEntry, (void*)bootArgsPreLion, NULL, NULL); startprog( kernelEntry, bootArgsPreLion ); } // Not reached return 0; }
int main(int argc, char** argv) { int ch; boolean priority_mode = TRUE; boolean test_mode = FALSE; boolean disable_partial_commit = FALSE; boolean full_commit_check = FALSE; boolean break_priority = FALSE; int break_priority_node = -1; boolean disable_hook = FALSE; char *commit_comment = NULL; /* this is needed before calling certain glib functions */ g_type_init(); //grab inputs while ((ch = getopt(argc, argv, "xdpthsecoafb:rlC:")) != -1) { switch (ch) { case 'x': g_old_print_output = TRUE; break; case 'd': g_debug = TRUE; break; case 'h': usage(); exit(0); break; case 'p': priority_mode = FALSE; break; case 't': test_mode = TRUE; break; case 's': g_dump_trans = TRUE; break; case 'e': g_display_error_node = TRUE; break; case 'c': g_coverage = TRUE; break; case 'o': disable_partial_commit = TRUE; break; case 'a': g_dump_actions = TRUE; break; case 'f': full_commit_check = TRUE; break; case 'b': break_priority_node = strtoul(optarg,NULL,10); break_priority = TRUE; break; case 'r': disable_hook = TRUE; break; case 'C': commit_comment = strdup(optarg); break; case 'l': release_config_lock(); break; default: usage(); exit(0); } } //can also be set via environment variable if (getenv("VYATTA_OUTPUT_ERROR_LOCATION") != NULL) { g_print_error_location_all = TRUE; } if (disable_hook == FALSE) { execute_hook(PRE_COMMIT_HOOK_DIR,commit_comment); } initialize_output("Commit"); init_paths(TRUE); d_dplog("commit2: starting up"); if (get_config_lock() != 0) { fprintf(out_stream, "Configuration system temporarily locked " "due to another commit in progress\n"); exit(1); } //get local session data plus configuration data GNode *config_data = common_get_local_session_data(); if (g_node_n_children(config_data) == 0) { common_commit_clean_temp_config(NULL, test_mode); fprintf(out_stream, "No configuration changes to commit\n"); return 0; } GNode *orig_node_tree = g_node_copy(config_data); // Get collection of transactions, i.e. trans nodes that have been activated. GNode *trans_coll = get_transactions(config_data, priority_mode); if (trans_coll == NULL) { printf("commit2: transactions collection is empty, exiting\n"); exit(0); } if (g_debug == TRUE || g_dump_trans == TRUE) { if (g_dump_trans == TRUE) { fprintf(out_stream,"Dumping transactions\n"); syslog(LOG_DEBUG,"Dumping transactions"); } //iterate over config_data and dump... g_node_traverse(trans_coll, G_PRE_ORDER, G_TRAVERSE_ALL, -1, (GNodeTraverseFunc)dump_func, (gpointer)NULL); if (g_dump_trans == TRUE) { exit(0); } } set_in_commit(TRUE); GNode *trans_child_node = (GNode*)g_node_first_child(trans_coll); if (trans_child_node == NULL) { printf("commit2: No child nodes to process, exiting\n"); exit(0); } //open the changes file and clear FILE *fp_changes = fopen(COMMIT_CHANGES_FILE,"w"); if (fp_changes == NULL) { cond_plog(true, LOG_ERR, "commit2: Cannot access changes file, exiting"); exit(0); } GSList *completed_root_node_coll = NULL; GSList *nodes_visited_coll = NULL; int errors = 0; int i = 0; do { boolean success = FALSE; d_dplog("commit2: Starting new transaction processing pass on root: [%s]", ((trans_child_node && trans_child_node->data && ((struct VyattaNode*)(trans_child_node->data))->_data._name) ? ((struct VyattaNode*)(trans_child_node->data))->_data._name : "")); if (break_priority) { gpointer gp = ((GNode*)trans_child_node)->data; long p = (long) ((struct VyattaNode*)gp)->_config._priority; if (p >= break_priority_node) { g_dump_trans = TRUE; g_node_traverse(trans_child_node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, (GNodeTraverseFunc)dump_func, (gpointer)NULL); g_dump_trans = FALSE; fprintf(out_stream,"Press any key to commit...\n"); // Wait for single character char input = getchar(); input = input; //to fix stupid compilier warning } } //complete() now requires a undisturbed copy of the trans_child_node tree GNode *comp_cp_node = g_node_copy(trans_child_node); if (g_dump_actions == TRUE) { fprintf(out_stream,"\n"); //add an extra line here } //on each priority node now execute actions nodes_visited_coll = NULL; if (validate_configuration(trans_child_node, full_commit_check, &nodes_visited_coll) == TRUE && (success = process_priority_node(trans_child_node)) == TRUE) { //this below copies the node directory from the local to active location //if this is true root skip if (trans_child_node != NULL && trans_child_node->data != NULL && strcmp(((struct VyattaNode*)(trans_child_node->data)) ->_data._path, "/") == 0) { //no op, need better way to define true root } else { if (disable_partial_commit == FALSE && g_dump_actions == FALSE) { completed_root_node_coll = g_slist_append(completed_root_node_coll, comp_cp_node); } } } if (g_dump_actions == TRUE) { success = TRUE; //FORCE SUCCESS ON DISPLAY MODE OF ACTIONS } if (success == FALSE) { errors |= 1; d_dplog("commit2: Failed in processing node"); } else { errors |= 2; } //now update the changes file update_change_file(fp_changes,nodes_visited_coll); fflush(fp_changes); ++i; } while ((trans_child_node = (GNode*) g_node_nth_child((GNode*) trans_coll, (guint) i)) != NULL); if (errors == 2) { /* * Need to add to the following func below to clean up dangling .wh. files */ if (g_dump_actions == FALSE) { common_commit_copy_to_live_config(orig_node_tree, TRUE, test_mode); common_commit_clean_temp_config(orig_node_tree, test_mode); } d_dplog("commit2: successful commit, now cleaning up temp directories"); } else { fprintf(out_stream,"Commit failed\n"); complete(completed_root_node_coll, test_mode); } set_in_commit(FALSE); d_dplog("DONE"); if (fp_changes != NULL) { fclose(fp_changes); } restore_output(); if (disable_hook == FALSE) { if (errors == 2) { setenv(ENV_COMMIT_STATUS,"SUCCESS",1); } else if (errors == 3) { setenv(ENV_COMMIT_STATUS,"PARTIAL",1); } else { setenv(ENV_COMMIT_STATUS,"FAILURE",1); } execute_hook(POST_COMMIT_HOOK_DIR,commit_comment); unsetenv(ENV_COMMIT_STATUS); } //remove tmp changes file as all the work is now done unlink(COMMIT_CHANGES_FILE); exit (errors == 2 ? 0 : 1); }
long DecodeKernel(void *binary, entry_t *rentry, char **raddr, int *rsize) { long ret = 0; compressed_kernel_header * kernel_header = (compressed_kernel_header *) binary; u_int32_t uncompressed_size = 0, size = 0, adler32 = 0; void *buffer = NULL; unsigned long len = 0; /*#if 0 printf("kernel header:\n"); printf("signature: 0x%x\n", kernel_header->signature); printf("compress_type: 0x%x\n", kernel_header->compress_type); printf("adler32: 0x%x\n", kernel_header->adler32); printf("uncompressed_size: 0x%x\n", kernel_header->uncompressed_size); printf("compressed_size: 0x%x\n", kernel_header->compressed_size); getchar(); #endif*/ if (kernel_header->signature == OSSwapBigToHostConstInt32('comp')) { DBG("Decompressing Kernel: "); if ((kernel_header->compress_type != OSSwapBigToHostConstInt32('lzss')) && (kernel_header->compress_type != OSSwapBigToHostConstInt32('lzvn'))) { error("ERROR: kernel compression is bad!\n"); return -1; } #if NOTDEF if (kernel_header->platform_name[0] && strcmp(gPlatformName, kernel_header->platform_name)) { return -1; } if (kernel_header->root_path[0] && strcmp(gBootFile, kernel_header->root_path)) { return -1; } #endif uncompressed_size = OSSwapBigToHostInt32(kernel_header->uncompressed_size); binary = buffer = malloc(uncompressed_size); // MinusZwei size = 0; switch (kernel_header->compress_type) { case OSSwapBigToHostConstInt32('lzvn'): size = decompress_lzvn( binary, uncompressed_size, &kernel_header->data[0], OSSwapBigToHostInt32(kernel_header->compressed_size)); break; case OSSwapBigToHostConstInt32('lzss'): size = decompress_lzss( (u_int8_t *)binary, uncompressed_size, &kernel_header->data[0], OSSwapBigToHostInt32(kernel_header->compressed_size)); break; default: break; } // MinusZwei if (uncompressed_size != size) { if ( kernel_header->compress_type == OSSwapBigToHostConstInt32('lzvn')) { error("ERROR: size mismatch from lzvn (found: %x, expected: %x).\n", size, uncompressed_size); } if ( kernel_header->compress_type == OSSwapBigToHostConstInt32('lzss')) { error("ERROR: size mismatch from lzss (found: %x, expected: %x).\n", size, uncompressed_size); } return -1; } adler32 = Adler32(binary, uncompressed_size); if (OSSwapBigToHostInt32(kernel_header->adler32) != adler32) { error("ERROR: adler mismatch (found: %x, expected: %x).\n", adler32, OSSwapBigToHostInt32(kernel_header->adler32)); return -1; } DBG("OK.\n"); } ret = ThinFatFile(&binary, &len); if (ret == 0 && len == 0 && archCpuType==CPU_TYPE_X86_64) { archCpuType=CPU_TYPE_I386; ret = ThinFatFile(&binary, &len); } // Bungo: no range checking, sorry size = 0; while (memcmp((uint8_t *)binary + size, (uint8_t *)gDarwinBuildVerStr, 21)) { size++; } gDarwinBuildVerStr = (char *)binary + size; // Notify modules that the kernel has been decompressed, thinned and is about to be decoded execute_hook("DecodeKernel", (void*)binary, NULL, NULL, NULL); ret = DecodeMachO(binary, rentry, raddr, rsize); if (ret < 0 && archCpuType == CPU_TYPE_X86_64) { archCpuType = CPU_TYPE_I386; ret = DecodeMachO(binary, rentry, raddr, rsize); } return ret; }
long DecodeKernel(void *binary, entry_t *rentry, char **raddr, int *rsize) { long ret; compressed_kernel_header * kernel_header = (compressed_kernel_header *) binary; u_int32_t uncompressed_size, size; void *buffer; unsigned long len; #if 0 printf("kernel header:\n"); printf("signature: 0x%x\n", kernel_header->signature); printf("compress_type: 0x%x\n", kernel_header->compress_type); printf("adler32: 0x%x\n", kernel_header->adler32); printf("uncompressed_size: 0x%x\n", kernel_header->uncompressed_size); printf("compressed_size: 0x%x\n", kernel_header->compressed_size); getchar(); #endif if (kernel_header->signature == OSSwapBigToHostConstInt32('comp')) { if (kernel_header->compress_type != OSSwapBigToHostConstInt32('lzss')) { error("kernel compression is bad\n"); return -1; } #if NOTDEF if (kernel_header->platform_name[0] && strcmp(gPlatformName, kernel_header->platform_name)) return -1; if (kernel_header->root_path[0] && strcmp(gBootFile, kernel_header->root_path)) return -1; #endif uncompressed_size = OSSwapBigToHostInt32(kernel_header->uncompressed_size); binary = buffer = malloc(uncompressed_size); size = decompress_lzss((u_int8_t *) binary, &kernel_header->data[0], OSSwapBigToHostInt32(kernel_header->compressed_size)); if (uncompressed_size != size) { error("size mismatch from lzss: %x\n", size); return -1; } if (OSSwapBigToHostInt32(kernel_header->adler32) != Adler32(binary, uncompressed_size)) { printf("adler mismatch\n"); return -1; } } ret = ThinFatFile(&binary, &len); if (ret == 0 && len == 0 && archCpuType==CPU_TYPE_X86_64) { archCpuType=CPU_TYPE_I386; ret = ThinFatFile(&binary, &len); } // Notify modules that the kernel has been decompressed, thinned and is about to be decoded execute_hook("DecodeKernel", (void*)binary, NULL, NULL, NULL); ret = DecodeMachO(binary, rentry, raddr, rsize); if (ret<0 && archCpuType==CPU_TYPE_X86_64) { archCpuType=CPU_TYPE_I386; ret = DecodeMachO(binary, rentry, raddr, rsize); } return ret; }
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 > 0) { // 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=-1; 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--; } } // Jief : In case the default partition (returned by selectBootVolume) is not in the menu if ( selectIndex == -1 ) { selectIndex = 0; // gDeviceCount is actually > 0, so menuItems[selectIndex] exists menuBVR = (BVRef)(menuItems[selectIndex].param); // what happen is bvChain is empty ? } } 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 KEY_ENTER: 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, "log") == 0) { showTextBuffer(msgbuf, strlen(msgbuf)); } 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 KEY_ESC: clearBootArgs(); break; case KEY_F5: // 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 KEY_F10: gScanSingleDrive = false; scanDisks(gBIOSDev, &bvCount); gBootVolume = NULL; clearBootArgs(); break; case KEY_TAB: // 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; } execute_hook("BootOptions", gBootArgs, gBootArgsPtr, NULL, NULL); return 0; }
/* * Initialize the module system by loading the Symbols.dylib module. * Once loaded, locate the _lookup_symbol function so that internal * symbols can be resolved. */ int init_module_system() { // Start any modules that were compiled in first. start_built_in_modules(); int retVal = 0; void (*module_start)(void) = NULL; extern char symbols_start __asm("section$start$__DATA$__Symbols"); char* module_data = &symbols_start; // Intialize module system if(module_data) { // Module system was compiled in (Symbols.dylib addr known) module_start = parse_mach(module_data, &load_module, &add_symbol, NULL); if(module_start && (module_start != (void*)0xFFFFFFFF)) { // Notify the system that it was laoded module_loaded(SYMBOLS_MODULE, module_start, SYMBOLS_AUTHOR, SYMBOLS_DESCRIPTION, SYMBOLS_VERSION, SYMBOLS_COMPAT); (*module_start)(); // Start the module. This will point to load_all_modules due to the way the dylib was constructed. DBG("Module %s Loaded.\n", SYMBOLS_MODULE); retVal = 1; } else { // The module does not have a valid start function printf("Unable to start %s at 0x%x\n", SYMBOLS_MODULE, module_data); pause(); } } // Look for modules located in the multiboot header. if(gMI && (gMI->mi_flags & MULTIBOOT_INFO_HAS_MODS)) { if(gMI->mi_mods_count) { struct multiboot_module* mod = (struct multiboot_module*)gMI->mi_mods_addr; while(gMI->mi_mods_count--) { if(mod->mm_string) { // Convert string to module name, check for dylib. if(strcmp(&mod->mm_string[strlen(mod->mm_string) - sizeof("dylib")], ".dylib") == 0) { module_data = (char*)mod->mm_mod_start; char* last = strrchr(mod->mm_string, '/'); if(last) { last++; } else { last = mod->mm_string; } char *name = strdup(last); name[strlen(last) - sizeof("dylib")] = 0; DBG("Loading multiboot module %s\n", name); module_start = parse_mach(module_data, &load_module, &add_symbol, NULL); if(module_start && (module_start != (void*)0xFFFFFFFF)) { // Notify the system that it was laoded module_loaded(name, module_start, NULL, NULL, 0, 0 /*moduleName, NULL, moduleVersion, moduleCompat*/); (*module_start)(); // Start the module DBG("Module %s Loaded.\n", name); DBGPAUSE(); } } } } } } if(retVal) execute_hook("ModulesLoaded", NULL, NULL, NULL, NULL); return retVal; }
void setup_pci_devs(pci_dt_t *pci_dt) { char *devicepath; bool doit, do_eth_devprop, do_wifi_devprop, /*do_usb_devprop,*/ do_gfx_devprop, do_enable_hpet, do_hda_devprop = false; pci_dt_t *current = pci_dt; getBoolForKey(kEthernetBuiltIn, &do_eth_devprop, &bootInfo->chameleonConfig); getBoolForKey(kEnableWifi, &do_wifi_devprop, &bootInfo->chameleonConfig); getBoolForKey(kGraphicsEnabler, &do_gfx_devprop, &bootInfo->chameleonConfig); // getBoolForKey(kUsbInject, &do_usb_devprop, &bootInfo->chameleonConfig); getBoolForKey(kHDAEnabler, &do_hda_devprop, &bootInfo->chameleonConfig); getBoolForKey(kForceHPET, &do_enable_hpet, &bootInfo->chameleonConfig); while (current) { devicepath = get_pci_dev_path(current); switch (current->class_id) { case PCI_CLASS_BRIDGE_HOST: //DBG("Setup BRIDGE_HOST \n"); if (current->dev.addr == PCIADDR(0, 0, 0)) { dram_controller_dev = current; } break; case PCI_CLASS_NETWORK_ETHERNET: //DBG("Setup ETHERNET %s enabled\n", do_eth_devprop?"":"no"); if (do_eth_devprop) { setup_eth_builtin(current); } break; case PCI_CLASS_NETWORK_OTHER: //DBG("Setup WIRELESS %s enabled\n", do_wifi_devprop?"":"no"); if (do_wifi_devprop) { setup_wifi_airport(current); } break; case PCI_CLASS_DISPLAY_VGA: //DBG("GraphicsEnabler %s enabled\n", do_gfx_devprop?"":"no"); if (do_gfx_devprop) { switch (current->vendor_id) { case PCI_VENDOR_ID_ATI: if (getBoolForKey(kSkipAtiGfx, &doit, &bootInfo->chameleonConfig) && doit) { verbose("Skip ATi/AMD gfx device!\n"); } else { setup_ati_devprop(current); } break; case PCI_VENDOR_ID_INTEL: if (getBoolForKey(kSkipIntelGfx, &doit, &bootInfo->chameleonConfig) && doit) { verbose("Skip Intel gfx device!\n"); } else { setup_gma_devprop(current); } break; case PCI_VENDOR_ID_NVIDIA: if (getBoolForKey(kSkipNvidiaGfx, &doit, &bootInfo->chameleonConfig) && doit) { verbose("Skip Nvidia gfx device!\n"); } else { setup_nvidia_devprop(current); } break; } } break; case PCI_CLASS_MULTIMEDIA_AUDIO_DEV: //DBG("Setup HDEF %s enabled\n", do_hda_devprop?"":"no"); if (do_hda_devprop) { setup_hda_devprop(current); } break; case PCI_CLASS_SERIAL_USB: //DBG("USB fix \n"); notify_usb_dev(current); /*if (do_usb_devprop) { set_usb_devprop(current); }*/ break; case PCI_CLASS_BRIDGE_ISA: //DBG("Force HPET %s enabled\n", do_enable_hpet?"":"no"); if (do_enable_hpet) { force_enable_hpet(current); } break; } execute_hook("PCIDevice", current, NULL, NULL, NULL); //DBG("setup_pci_devs current devID=%08x\n", current->device_id); setup_pci_devs(current->children); current = current->next; } }
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; }
//========================================================================== // 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 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); } }
long LoadMatchedModules( void ) { TagPtr prop; ModulePtr module; char *fileName, segName[32]; DriverInfoPtr driver; long length, driverAddr, driverLength; void *executableAddr = 0; module = gModuleHead; while (module != 0) { if (module->willLoad) { prop = XMLGetProperty(module->dict, kPropCFBundleExecutable); if (prop != 0) { fileName = prop->string; snprintf(gFileSpec, 4096, "%s%s", module->executablePath, fileName); length = LoadThinFatFile(gFileSpec, &executableAddr); if (length == 0) { length = LoadFile(gFileSpec); executableAddr = (void *)kLoadAddr; } // printf("%s length = %d addr = 0x%x\n", gFileSpec, length, driverModuleAddr); getchar(); } else length = 0; if (length != -1) { // driverModuleAddr = (void *)kLoadAddr; // if (length != 0) // { // ThinFatFile(&driverModuleAddr, &length); // } // Make make in the image area. execute_hook("LoadMatchedModules", module, &length, executableAddr, NULL); driverLength = sizeof(DriverInfo) + module->plistLength + length + module->bundlePathLength; driverAddr = AllocateKernelMemory(driverLength); // Set up the DriverInfo. driver = (DriverInfoPtr)driverAddr; driver->plistAddr = (char *)(driverAddr + sizeof(DriverInfo)); driver->plistLength = module->plistLength; if (length != 0) { driver->executableAddr = (void *)(driverAddr + sizeof(DriverInfo) + module->plistLength); driver->executableLength = length; } else { driver->executableAddr = 0; driver->executableLength = 0; } driver->bundlePathAddr = (void *)(driverAddr + sizeof(DriverInfo) + module->plistLength + driver->executableLength); driver->bundlePathLength = module->bundlePathLength; // Save the plist, module and bundle. strcpy(driver->plistAddr, module->plistAddr); if (length != 0) { memcpy(driver->executableAddr, executableAddr, length); } strcpy(driver->bundlePathAddr, module->bundlePath); // Add an entry to the memory map. snprintf(segName, sizeof(segName), "Driver-%lx", (unsigned long)driver); AllocateMemoryRange(segName, driverAddr, driverLength, kBootDriverTypeKEXT); } } module = module->nextModule; } return 0; }
static int ExecKernel(void *binary) { entry_t kernelEntry; int ret; bootArgs->kaddr = bootArgs->ksize = 0; execute_hook("ExecKernel", (void*)binary, NULL, NULL, NULL); //Azi: gHaveKernelCache is set here ret = DecodeKernel(binary, &kernelEntry, (char **) &bootArgs->kaddr, (int *)&bootArgs->ksize ); if ( ret != 0 ) return ret; // Reserve space for boot args reserveKernBootStruct(); //Azi: ... // Load boot drivers from the specifed root path, // if we don't have a prelinked kernel - check load.c 43 & 264 if (!gHaveKernelCache) { LoadDrivers("/"); } clearActivityIndicator(); if (gErrors) { printf("Errors encountered while starting up the computer.\n"); printf("Pausing %d seconds...\n", kBootErrorTimeout); sleep(kBootErrorTimeout); } setupFakeEfi(); //Azi: check position on Mek (plkernel) md0Ramdisk(); verbose("Starting Darwin %s\n",( archCpuType == CPU_TYPE_I386 ) ? "x86" : "x86_64"); // Cleanup the PXE base code. if ( (gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit ) { if ( (ret = nbpUnloadBaseCode()) != nbpStatusSuccess ) { printf("nbpUnloadBaseCode error %d\n", (int) ret); sleep(2); } } bool dummyVal; //Azi: Wait=y is breaking other keys when typed "after them" at boot prompt. // Works properly if typed in first place or used on Boot.plist. if (getBoolForKey(kWaitForKeypressKey, &dummyVal, &bootInfo->bootConfig) && dummyVal) { printf("(Wait) "); // Add to trunk?? don't forget that puse uses printf, not verbose!! pause(); } usb_loop(); //autoresolution - Check if user disabled AutoResolution at the boot prompt. // we can't check the plist here if we have AutoResolution=n there and we anabled it // at boot prompt...????? // getBoolForKey(kAutoResolutionKey, &gAutoResolution, &bootInfo->bootConfig); finishAutoRes(); //Azi: closing Vbios after "if (gVerboseMode)" stuff eliminates the need for setting // AutoResolution = true above; but creates another bug when booting in TextMode with -v arg. // Simptoms include: staring some seconds at a nicely drawn white screen, after boot prompt. // Think i'm just going to end up removing setting gAutoResolution = false // on closeVbios().. the more i think, the less sense it makes doing it there!! //autoresolution - end // Notify modules that the kernel is about to be started // testing... if (gMacOSVersion[3] <= '6') execute_hook("Kernel Start", (void*)kernelEntry, (void*)bootArgsPreLion, NULL, NULL); else execute_hook("Kernel Start", (void*)kernelEntry, (void*)bootArgs, NULL, NULL); // If we were in text mode, switch to graphics mode. // This will draw the boot graphics unless we are in // verbose mode. if(gVerboseMode) setVideoMode( GRAPHICS_MODE, 0 ); else drawBootGraphics(); setupBooterLog(); finalizeBootStruct(); //Azi: see asm.s LABEL(_disableIRQs) // outb(0x21, 0xff); // outb(0xa1, 0xff); // Jump to kernel's entry point. There's no going back now. if (gMacOSVersion[3] <= '6') startprog( kernelEntry, bootArgsPreLion ); else startprog( kernelEntry, bootArgs ); // Not reached return 0; }