void setBootGlobals(BVRef chain) { // Record default boot device. gBootVolume = selectBootVolume(chain); // turbo - Save the ORIGINAL boot volume too for loading our mkext if (!gBIOSBootVolume) gBIOSBootVolume = gBootVolume; setRootVolume(gBootVolume); }
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 (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->bootConfig)) { /* 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; } // 18seven's Quick-args macro bool f8 = false, altf = false, shiftf = false, alts = false, altv = false, altx = false; // x32 = false, x64 = false; while (readKeyboardStatus()) { key = bgetc (); if (key == 0x4200) f8 = true; if (key == 0x2100) altf = true; if (key == 0x0046) shiftf = true; if (key == 0x1F00) alts = true; if (key == 0x2F00) altv = true; if (key == 0x2D00) altx = true; /* if (key == 0x0004) x32 = true; if (key == 0x0007) x64 = true; */ } // If user typed F8, abort quiet mode, and display the menu. if (f8) { gBootMode &= ~kBootModeQuiet; timeout = 0; } // If user typed 'alt-v', boot in verbose mode. if ((gBootMode & kBootModeQuiet) && firstRun && altv) { addBootArg(kVerboseModeFlag); } // If user typed 'alt-s', boot in single user mode. if ((gBootMode & kBootModeQuiet) && firstRun && alts) { addBootArg(kSingleUserModeFlag); } if ((gBootMode & kBootModeQuiet) && firstRun && altf) { addBootArg(kIgnoreCachesFlag); } if ((gBootMode & kBootModeQuiet) && firstRun && shiftf) { addBootArg(kIgnoreBootFileFlag); } if ((gBootMode & kBootModeQuiet) && firstRun && altx) { addBootArg(kSafeModeFlag); } /* if ((gBootMode & kBootModeQuiet) && firstRun && x32) { addBootArg(k32BitModeFlag); } if ((gBootMode & kBootModeQuiet) && firstRun && x64) { addBootArg(k64BitModeFlag); } */ 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->bootConfig)) { 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->bootConfig )) { // 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 == GRAPHICS_MODE) { // redraw the background buffer gui.logo.draw = true; drawBackground(); gui.devicelist.draw = true; gui.redraw = true; if (!(gBootMode & kBootModeQuiet)) { bool showBootBanner = true; // Check if "Boot Banner"=N switch is present in config file. getBoolForKey(kBootBannerKey, &showBootBanner, &bootInfo->bootConfig); 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 == GRAPHICS_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 = getc(); 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 == GRAPHICS_MODE) { showInfoBox(getVBEInfoString(), getVBEModeInfoString()); } else { printVBEModeInfo(); } } else if ( strcmp( booterCommand, "memory" ) == 0) { if (bootArgs->Video.v_display == GRAPHICS_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 kF2Key: /* * AutoResolution - Reapply the patch if Graphics Mode was incorrect or EDID Info was insane */ if ((gAutoResolution == TRUE) && map) { // get the new Graphics Mode key processBootOptions(); UInt32 params[4]; params[3] = 0; //Has the target Resolution Changed ? int count = getNumberArrayFromProperty(kGraphicsModeKey, params, 4); if ( count < 3 ) getResolution(params); if ((params[0] != 0) && (params[1] != 0) && (params[0] != map->currentX) && (params[1] != map->currentY)) { //Go back to TEXT mode while we change the mode if (bootArgs->Video.v_display == GRAPHICS_MODE) { CursorState cursorState; setVideoMode(VGA_TEXT_MODE, 0); setCursorPosition(0, 0, 0); clearScreenRows(0, kScreenLastRow); changeCursor( 0, 0, kCursorTypeHidden, &cursorState ); //Reapply patch in case resolution have changed patchVbios(map, params[0], params[1], params[2], 0, 0); if (useGUI && (gui.initialised == true)) initGUI(); // Make sure all values are set if (bootArgs->Video.v_display != GRAPHICS_MODE) bootArgs->Video.v_display = GRAPHICS_MODE; if (!useGUI) useGUI = true; // redraw the background buffer drawBackground(); gui.devicelist.draw = true; gui.redraw = true; if (!(gBootMode & kBootModeQuiet)) { bool showBootBanner = true; // Check config file. getBoolForKey(kBootBannerKey, &showBootBanner, &bootInfo->bootConfig); 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); } nextRow = kMenuTopRow; showPrompt = true; if (gDeviceCount) { 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 ); //this is used to avoid resetting the incorrect mode while quiting the boot menu map->hasSwitched = true; } } clearBootArgs(); key = 0; } 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) { 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 ); /* * AutoResolution - make sure all values are set */ bootArgs->Video.v_display = VGA_TEXT_MODE; useGUI = false; } else { gui.redraw = true; setVideoMode(GRAPHICS_MODE, 0); /* * AutoResolution - make sure all values are set */ bootArgs->Video.v_display = GRAPHICS_MODE; useGUI = true; updateVRAM(); } 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; } 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 = false; 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. // This is not a mandatory operation anymore. loadOverrideConfig(&bootInfo->overrideConfig); // 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) )) { strcpy( bootInfo->bootFile, kernel ); gOverrideKernel = true; } else { if ( getValueForKey( kKernelNameKey, &val, &cnt, &bootInfo->bootConfig ) ) { strlcpy( bootInfo->bootFile, val, cnt+1 ); if (strcmp( bootInfo->bootFile, kDefaultKernel ) != 0) { gOverrideKernel = true; } } 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) || !getValueForKey( kKernelFlagsKey, &val, &cnt, &bootInfo->bootConfig )) { val = ""; cnt = 0; } configKernelFlags = 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 = true; } else { // // Try an alternate method for getting the root UUID on boot helper partitions. // if (gBootVolume->flags & kBVFlagBooter) { if((loadHelperConfig(&bootInfo->helperConfig) == 0) && getValueForKey(kHelperRootUUIDKey, &val, &cnt, &bootInfo->helperConfig) ) { getValueForKey(kHelperRootUUIDKey, &val, &cnt, &bootInfo->helperConfig); copyArgument(kBootUUIDKey, val, cnt, &argP, &cntRemaining); uuidSet = true; } } if (!uuidSet && gBootVolume->fs_getuuid && gBootVolume->fs_getuuid (gBootVolume, uuidStr) == 0) { verbose("Setting boot-uuid to: %s\n", uuidStr); copyArgument(kBootUUIDKey, uuidStr, strlen(uuidStr), &argP, &cntRemaining); uuidSet = true; } } if (!processBootArgument(kRootDeviceKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, gRootDevice)) { cnt = 0; if ( getValueForKey( kBootDeviceKey, &val, &cnt, &bootInfo->bootConfig)) { 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)); } /* * Removed. We don't need this anymore. * 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'; if(!shouldboot) { gVerboseMode = getValueForKey( kVerboseModeFlag, &val, &cnt, &bootInfo->bootConfig ) || getValueForKey( kSingleUserModeFlag, &val, &cnt, &bootInfo->bootConfig ); gBootMode = ( getValueForKey( kSafeModeFlag, &val, &cnt, &bootInfo->bootConfig ) ) ? kBootModeSafe : kBootModeNormal; if ( getValueForKey( kIgnoreCachesFlag, &val, &cnt, &bootInfo->bootConfig ) ) { gBootMode = kBootModeSafe; } } if ( getValueForKey( kMKextCacheKey, &val, &cnt, &bootInfo->bootConfig ) ) { strlcpy(gMKextName, val, cnt + 1); } free(configKernelFlags); free(valueBuffer); return 0; }
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; }
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; } // Find out which version mac os we're booting. strncpy(gMacOSVersion, gBootVolume->OSVersion, sizeof(gMacOSVersion)); // 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, NULL); // 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 { if( YOSEMITE ) // is 10.10 { strlcpy( bootInfo->bootFile, kOSXKernel, sizeof(bootInfo->bootFile) ); //printf(HEADER "/System/Library/Kernels/%s\n", bootInfo->bootFile); } else { // OSX is not 10.10 strlcpy( bootInfo->bootFile, kDefaultKernel, sizeof(bootInfo->bootFile) ); //printf(HEADER "/%s\n", bootInfo->bootFile); } } } if (!YOSEMITE) // not 10.10 so 10.9 and previus { if (strcmp( bootInfo->bootFile, kDefaultKernel ) != 0) { //printf(HEADER "org.chameleon.Boot.plist found path for custom '%s' found!\n", bootInfo->bootFile); gOverrideKernel = true; } } else { // OSX is 10.10 if (strcmp( bootInfo->bootFile, kOSXKernel ) != 0) { //printf(HEADER "org.chameleon.Boot.plist found path for custom '%s' found!\n", bootInfo->bootFile); gOverrideKernel = true; } } // Ermac : Inject "kext-dev-mode=1" if OS X 10.10 is detected if( YOSEMITE ) // is 10.10 { addBootArg("kext-dev-mode=1"); } 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); } // Try to get the volume uuid string if (!strlen(gBootUUIDString) && gBootVolume->fs_getuuid) { gBootVolume->fs_getuuid(gBootVolume, gBootUUIDString); DBG("boot-uuid: %s\n", gBootUUIDString); } } 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; }
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; }
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; }