Пример #1
0
//==========================================================================
// The 'main' function for the booter. Called by boot0 when booting
// from a block device, or by the network booter.
//
// arguments:
//   biosdev - Value passed from boot1/NBP to specify the device
//             that the booter was loaded from.
//
// If biosdev is kBIOSDevNetwork, then this function will return if
// booting was unsuccessful. This allows the PXE firmware to try the
// next boot device on its list.
void common_boot(int biosdev)
{
    int      status;
    char     *bootFile;
    unsigned long adler32;
    bool     quiet;
    bool     firstRun = true;
    bool     instantMenu;
    bool     rescanPrompt;
    unsigned int allowBVFlags = kBVFlagSystemVolume|kBVFlagForeignBoot;
    unsigned int denyBVFlags = kBVFlagEFISystem;

    // Set reminder to unload the PXE base code. Neglect to unload
    // the base code will result in a hang or kernel panic.
    gUnloadPXEOnExit = true;

    // Record the device that the booter was loaded from.
    gBIOSDev = biosdev & kBIOSDevMask;

    // Initialize boot info structure.
    initKernBootStruct();

    // 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 = loadSystemConfig(&bootInfo->bootConfig);

    if (getBoolForKey(kQuietBootKey, &quiet, &bootInfo->bootConfig) && quiet) {
        gBootMode |= kBootModeQuiet;
    }

    // Override firstRun to get to the boot menu instantly by setting "Instant Menu"=y in system config
    if (getBoolForKey(kInsantMenuKey, &instantMenu, &bootInfo->bootConfig) && instantMenu) {
        firstRun = false;
    }

    // Loading preboot ramdisk if exists.
    loadPrebootRAMDisk();

    // Disable rescan option by default
    gEnableCDROMRescan = false;

    // Enable it with Rescan=y in system config
    if (getBoolForKey(kRescanKey, &gEnableCDROMRescan, &bootInfo->bootConfig) && gEnableCDROMRescan) {
        gEnableCDROMRescan = true;
    }

    // Ask the user for Rescan option by setting "Rescan Prompt"=y in system config.
    rescanPrompt = false;
    if (getBoolForKey(kRescanPromptKey, &rescanPrompt , &bootInfo->bootConfig) && rescanPrompt && biosDevIsCDROM(gBIOSDev)) {
        gEnableCDROMRescan = promptForRescanOption();
    }

    // Enable touching a single BIOS device only if "Scan Single Drive"=y is set in system config.
    if (getBoolForKey(kScanSingleDriveKey, &gScanSingleDrive, &bootInfo->bootConfig) && gScanSingleDrive) {
        gScanSingleDrive = true;
    }

    // Create a list of partitions on device(s).
    if (gScanSingleDrive) {
      scanBootVolumes(gBIOSDev, &bvCount);
    } else {
      scanDisks(gBIOSDev, &bvCount);
    }

    // Create a separated bvr chain using the specified filters.
    bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount);

    gBootVolume = selectBootVolume(bvChain);

#if DEBUG
    printf(" Default: %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBootVolume, gBootVolume->biosdev, gBootVolume->part_no, gBootVolume->flags);
    printf(" bt(0,0): %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBIOSBootVolume, gBIOSBootVolume->biosdev, gBIOSBootVolume->part_no, gBIOSBootVolume->flags);
    getc();
#endif

	
	useGUI = TRUE;
	// Override useGUI default
	getBoolForKey(kGUIKey, &useGUI, &bootInfo->bootConfig);
 	
 	// Before initGui, patch the video bios with the correct resolution
 	
 	UInt32 params[4];
 	int count;
 	params[3] = 0;
 	
	
 	autoResolution = TRUE;
 	// Override AutoResolution default
 	getBoolForKey(kAutoResolutionKey, &autoResolution, &bootInfo->bootConfig);
 	
	vbios_map * map = open_vbios(CT_UNKWN);
	//Saving the bios in case we have to unpatch it
	save_vbios(map);
	
 	if (autoResolution == TRUE) {
		//Get Resolution from Graphics Mode key
 		count = getNumberArrayFromProperty(kGraphicsModeKey, params, 4);
 		if ( count < 3 ){
			//If no Graphics Mode key, get from EDID
 			getResolution(&params[0], &params[1], &params[2]);
			verbose("EDID Resolution: %dx%d\n",params[0], params[1]);
 		}
	} else {
 			if ( params[2] == 256 ) params[2] = 8;
 			if ( params[2] == 555 ) params[2] = 16;
 			if ( params[2] == 888 ) params[2] = 32;
	}
 		
	if (params[0]!=0 && params[1]!=0) {	
  			
  			unlock_vbios(map);
  			
			patch_vbios(map, params[0], params[1], params[2], 0, 0);
  			
  			relock_vbios(map);
			#if AUTORES_DEBUG			
				printf("Press Any Key...\n");
			 	getc();
			#endif
	}
 	
		
    if (useGUI) {
        /* XXX AsereBLN handle error */
	initGUI();
    }

    setBootGlobals(bvChain);

    // Parse args, load and start kernel.
    while (1) {
        const char *val;
        int len;
        int trycache;
        long flags, cachetime, kerneltime, exttime, sleeptime, time;
        int ret = -1;
        void *binary = (void *)kLoadAddr;
        bool tryresume;
        bool tryresumedefault;
        bool forceresume;

        config_file_t    systemVersion;		// system.plist of booting partition

        // additional variable for testing alternate kernel image locations on boot helper partitions.
        char     bootFileSpec[512];
		
        // Initialize globals.

        sysConfigValid = false;
        gErrors        = false;

        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);
          }
          continue;
        }
		
        // Other status (e.g. 0) means that we should proceed with boot.
		
		if( bootArgs->Video.v_display == GRAPHICS_MODE )
			drawBackground();
			
        // Found and loaded a config file. Proceed with boot.

		// Turn off any GUI elements
		if( bootArgs->Video.v_display == GRAPHICS_MODE )
		{
			gui.devicelist.draw = false;
			gui.bootprompt.draw = false;
			gui.menu.draw = false;
			gui.infobox.draw = false;
			drawBackground();
			updateVRAM();
		}
		
		/*
		 * AutoResolution - Reapply the patch or cancel if Graphics Mode was incorrect
		 *                  or EDID Info was insane
		 */	
	     getBoolForKey(kAutoResolutionKey, &autoResolution, &bootInfo->bootConfig);
		
		//Restore the vbios for Cancelation
		if ((autoResolution == FALSE) && map) {
			
			unlock_vbios(map);
			
			restore_vbios(map);
			
			relock_vbios(map);
			
			close_vbios(map);
			
		} 
		if ((autoResolution == TRUE) && map) {
			//Reapply patch in case resolution have changed
			
			count = getNumberArrayFromProperty(kGraphicsModeKey, params, 4);
			if ( count < 3 ) {
				getResolution(&params[0], &params[1], &params[2]);
			}
			else 
			{
				if ( params[2] == 256 ) params[2] = 8;
				if ( params[2] == 555 ) params[2] = 16;
				if ( params[2] == 888 ) params[2] = 32;
			}
			
			if (params[0]!=0 && params[1]!=0) {
				
				unlock_vbios(map);
				
				patch_vbios(map, params[0], params[1], params[2], 0, 0);
				
				relock_vbios(map);
				
				close_vbios(map);
			}
		}
		
		// Find out which version mac os we're booting.
		if (!loadConfigFile("System/Library/CoreServices/SystemVersion.plist", &systemVersion)) {
			if (getValueForKey(kProductVersion, &val, &len, &systemVersion)) {	
				// getValueForKey uses const char for val
				// so copy it and trim
				strncpy(gMacOSVersion, val, MIN(len, 4));
				gMacOSVersion[MIN(len, 4)] = '\0';
			}
		}

		if (platformCPUFeature(CPU_FEATURE_EM64T)) {
			archCpuType = CPU_TYPE_X86_64;
		} else {
			archCpuType = CPU_TYPE_I386;
		}
		if (getValueForKey(karch, &val, &len, &bootInfo->bootConfig)) {
			if (strncmp(val, "i386", 4) == 0) {
				archCpuType = CPU_TYPE_I386;
			}
		}
		if (getValueForKey(k32BitModeFlag, &val, &len, &bootInfo->bootConfig)) {
			archCpuType = CPU_TYPE_I386;
		}
		
		if (!getBoolForKey (kWake, &tryresume, &bootInfo->bootConfig)) {
			tryresume = true;
			tryresumedefault = true;
		} else {
			tryresumedefault = false;
		}

		if (!getBoolForKey (kForceWake, &forceresume, &bootInfo->bootConfig)) {
			forceresume = false;
		}
		
		if (forceresume) {
			tryresume = true;
			tryresumedefault = false;
		}
		
		while (tryresume) {
			const char *tmp;
			BVRef bvr;
			if (!getValueForKey(kWakeImage, &val, &len, &bootInfo->bootConfig))
				val="/private/var/vm/sleepimage";
			
			// Do this first to be sure that root volume is mounted
			ret = GetFileInfo(0, val, &flags, &sleeptime);

			if ((bvr = getBootVolumeRef(val, &tmp)) == NULL)
				break;
			
			// Can't check if it was hibernation Wake=y is required
			if (bvr->modTime == 0 && tryresumedefault)
				break;
			
			if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat))
				break;
			
			if (!forceresume && ((sleeptime+3)<bvr->modTime)) {
				printf ("Hibernate image is too old by %d seconds. Use ForceWake=y to override\n",bvr->modTime-sleeptime);
				break;
			}
				
			HibernateBoot((char *)val);
			break;
		}

        // Reset cache name.
        bzero(gCacheNameAdler + 64, sizeof(gCacheNameAdler) - 64);

        sprintf(gCacheNameAdler + 64, "%s,%s", gRootDevice, bootInfo->bootFile);

        adler32 = Adler32((unsigned char *)gCacheNameAdler, sizeof(gCacheNameAdler));

        if (getValueForKey(kKernelCacheKey, &val, &len, &bootInfo->bootConfig)) {
            strlcpy(gBootKernelCacheFile, val, len+1);
        } else {
            sprintf(gBootKernelCacheFile, "%s.%08lX", kDefaultCachePath, adler32);
        }

        // Check for cache file.
        trycache = (((gBootMode & kBootModeSafe) == 0) &&
                    !gOverrideKernel &&
                    (gBootFileType == kBlockDeviceType) &&
                    (gMKextName[0] == '\0') &&
                    (gBootKernelCacheFile[0] != '\0'));

		verbose("Loading Darwin %s\n", gMacOSVersion);
		
        if (trycache) do {
      
            // if we haven't found the kernel yet, don't use the cache
            ret = GetFileInfo(NULL, bootInfo->bootFile, &flags, &kerneltime);
            if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)) {
                trycache = 0;
                break;
            }
            ret = GetFileInfo(NULL, gBootKernelCacheFile, &flags, &cachetime);
            if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)
                || (cachetime < kerneltime)) {
                trycache = 0;
                break;
            }
            ret = GetFileInfo("/System/Library/", "Extensions", &flags, &exttime);
            if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)
                && (cachetime < exttime)) {
                trycache = 0;
                break;
            }
            if (kerneltime > exttime) {
                exttime = kerneltime;
            }
            if (cachetime != (exttime + 1)) {
                trycache = 0;
                break;
            }
        } while (0);

        do {
            if (trycache) {
                bootFile = gBootKernelCacheFile;
                verbose("Loading kernel cache %s\n", bootFile);
                ret = LoadFile(bootFile);
                binary = (void *)kLoadAddr;
                if (ret >= 0) {
                    break;
                }
            }
            bootFile = bootInfo->bootFile;

            // Try to load kernel image from alternate locations on boot helper partitions.
            sprintf(bootFileSpec, "com.apple.boot.P/%s", bootFile);
            ret = GetFileInfo(NULL, bootFileSpec, &flags, &time); 
  	  	    if (ret == -1)
  	  	    {
              sprintf(bootFileSpec, "com.apple.boot.R/%s", bootFile);
              ret = GetFileInfo(NULL, bootFileSpec, &flags, &time); 
              if (ret == -1)
              {
                sprintf(bootFileSpec, "com.apple.boot.S/%s", bootFile);
                ret = GetFileInfo(NULL, bootFileSpec, &flags, &time); 
                if (ret == -1)
                {
                  // Not found any alternate locations, using the original kernel image path.
                  strcpy(bootFileSpec, bootFile);
                }
              }
            }
            			
            verbose("Loading kernel %s\n", bootFileSpec);
            ret = LoadThinFatFile(bootFileSpec, &binary);
            if (ret <= 0 && archCpuType == CPU_TYPE_X86_64)
            {
              archCpuType = CPU_TYPE_I386;
              ret = LoadThinFatFile(bootFileSpec, &binary);				
            }
			
        } while (0);

        clearActivityIndicator();
#if DEBUG
        printf("Pausing...");
        sleep(8);
#endif

        if (ret <= 0) {
			printf("Can't find %s\n", bootFile);

			if(gui.initialised) {
				sleep(1);
				drawBackground();
				gui.devicelist.draw = true;
				gui.redraw = true;
			}
            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 (getVideoMode() == GRAPHICS_MODE) {	// if we are already in graphics-mode,
		setVideoMode(VGA_TEXT_MODE, 0);	// switch back to text mode
	}
    }
	
    if ((gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit) {
	nbpUnloadBaseCode();
    }
}
Пример #2
0
Файл: boot.c Проект: aosm/boot
void boot(int biosdev)
{
    int      status;
    char     *bootFile;
    unsigned long adler32;
    BOOL     quiet;
    BOOL     firstRun = YES;
    BVRef    bvChain;

    zeroBSS();

    // Initialize malloc

    malloc_init(0, 0, 0, malloc_error);

    // Enable A20 gate before accessing memory above 1Mb.

    enableA20();

    // Set reminder to unload the PXE base code. Neglect to unload
    // the base code will result in a hang or kernel panic.

    gUnloadPXEOnExit = 1;

    // Record the device that the booter was loaded from.

    gBIOSDev = biosdev & kBIOSDevMask;

    // Initialize boot info structure.

    initKernBootStruct( gBIOSDev );

    // Setup VGA text mode.
    // Not sure if it is safe to call setVideoMode() before the
    // config table has been loaded. Call video_mode() instead.

    video_mode( 2 );  // 80x25 mono text mode.

    // Scan hardware configuration.

    scanHardware();

    // First get info for boot volume.
    bvChain = scanBootVolumes(gBIOSDev, 0);

    // Record default boot device.
    gBootVolume = selectBootVolume(bvChain);
    bootArgs->kernDev = MAKEKERNDEV(gBIOSDev,
                                    BIOS_DEV_UNIT(gBootVolume),
                                    gBootVolume->part_no );

    // Load default config file from boot device.
    status = loadSystemConfig(0, 0);

    if ( getBoolForKey( kQuietBootKey, &quiet ) && quiet ) {
        gBootMode |= kBootModeQuiet;
    }

    // Parse args, load and start kernel.

    while (1)
    {
        const char *val;
        int len;
        int trycache;
        long flags, cachetime, kerneltime, exttime;
        int ret = -1;

        // Initialize globals.

        sysConfigValid = 0;
        gErrors        = 0;

        status = getBootOptions(firstRun);
        firstRun = NO;
        if (status == -1) continue;

        status = processBootOptions();
        if ( status ==  1 ) break;
        if ( status == -1 ) continue;

        // Found and loaded a config file. Proceed with boot.


        // Reset cache name.
        bzero(gCacheNameAdler, sizeof(gCacheNameAdler));

        if ( getValueForKey( kRootDeviceKey, &val, &len ) == YES ) {
            if (*val == '*') {
                val++;
                len--;
            }
            strncpy( gCacheNameAdler + 64, val, len );
            sprintf(gCacheNameAdler + 64 + len, ",%s", bootArgs->bootFile);
        } else {
            strcpy(gCacheNameAdler + 64, bootArgs->bootFile);
        }
        adler32 = Adler32(gCacheNameAdler, sizeof(gCacheNameAdler));

        if (getValueForKey(kKernelCacheKey, &val, &len) == YES) {
            strlcpy(gBootKernelCacheFile, val, len+1);
        } else {
            sprintf(gBootKernelCacheFile, "%s.%08lX", kDefaultCachePath, adler32);
        }

        // Check for cache file.


        trycache = (((gBootMode & kBootModeSafe) == 0) &&
                    (gOverrideKernel == NO) &&
                    (gBootFileType == kBlockDeviceType) &&
                    (gMKextName[0] == '\0') &&
                    (gBootKernelCacheFile[0] != '\0'));

        printf("Loading Darwin/x86\n");

        if (trycache) do {
      
            // if we haven't found the kernel yet, don't use the cache
            ret = GetFileInfo(NULL, bootArgs->bootFile, &flags, &kerneltime);
            if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)) {
                trycache = 0;
                break;
            }
            ret = GetFileInfo(NULL, gBootKernelCacheFile, &flags, &cachetime);
            if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)
                || (cachetime < kerneltime)) {
                trycache = 0;
                break;
            }
            ret = GetFileInfo("/System/Library/", "Extensions", &flags, &exttime);
            if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)
                && (cachetime < exttime)) {
                trycache = 0;
                break;
            }
            if (kerneltime > exttime) {
                exttime = kerneltime;
            }
            if (cachetime != (exttime + 1)) {
                trycache = 0;
                break;
            }
        } while (0);

        do {
            if (trycache) {
                bootFile = gBootKernelCacheFile;
                verbose("Loading kernel cache %s\n", bootFile);
                ret = LoadFile(bootFile);
                if (ret >= 0) {
                    break;
                }
            }
            bootFile = bootArgs->bootFile;
            verbose("Loading kernel %s\n", bootFile);
            ret = LoadFile(bootFile);
        } while (0);

        clearActivityIndicator();
#if DEBUG
        printf("Pausing...");
        sleep(8);
#endif

        if (ret < 0) {
            error("Can't find %s\n", bootFile);

            if ( gBootFileType == kBIOSDevTypeFloppy )
            {
                // floppy in drive, but failed to load kernel.
                gBIOSDev = kBIOSDevTypeHardDrive;
                initKernBootStruct( gBIOSDev );
                printf("Attempting to load from hard drive...");
            }
            else if ( gBootFileType == kNetworkDeviceType )
            {
                // Return control back to PXE. Don't unload PXE base code.
                gUnloadPXEOnExit = 0;
                break;
            }
        } else {
            /* Won't return if successful. */
            ret = ExecKernel((void *)kLoadAddr);
        }

    } /* while(1) */
    
    if ((gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit) {
	nbpUnloadBaseCode();
    }
}
Пример #3
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;
}
Пример #4
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;
    }

    // reload the config, this time with the boot arg
    loadSystemConfig(gBootArgs, &bootInfo->bootConfig, NULL, true);

    // 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( kOldSafeModeFlag, &val, &cnt, &bootInfo->bootConfig ) ) {
        	gBootMode = kBootModeSafe;
   	}

   	if ( getValueForKey( kMKextCacheKey, &val, &cnt, &bootInfo->bootConfig ) ) {
        	strlcpy(gMKextName, val, cnt + 1);
    	}

    }
	 
    free(configKernelFlags);
    free(valueBuffer);

    return 0;
}
Пример #5
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;
}
Пример #6
0
int
processBootOptions()
{
    const char *     cp  = gBootArgs;
    const char *     val = 0;
    const char *     kernel;
    int              cnt;
    int		     userCnt;
    int              cntRemaining;
    char *           argP;
    char             uuidStr[64];
    BOOL             uuidSet = NO;
    char *           configKernelFlags;
    char *           valueBuffer;

    valueBuffer = (char *)malloc(VALUE_SIZE);

    skipblanks( &cp );

    // Update the unit and partition number.

    if ( gBootVolume )
    {
        if ( gBootVolume->flags & kBVFlagForeignBoot )
        {
            readBootSector( gBootVolume->biosdev, gBootVolume->part_boff,
                            (void *) 0x7c00 );

            //
            // Setup edx, and signal intention to chain load the
            // foreign booter.
            //

            chainbootdev  = gBootVolume->biosdev;
            chainbootflag = 1;

            return 1;
        }

        bootInfo->kernDev &= ~((B_UNITMASK << B_UNITSHIFT ) |
                          (B_PARTITIONMASK << B_PARTITIONSHIFT));

        bootInfo->kernDev |= MAKEKERNDEV(    0,
 		         /* unit */      BIOS_DEV_UNIT(gBootVolume),
                        /* partition */ gBootVolume->part_no );
    }

    // Load config table specified by the user, or use the default.

    if (getValueForBootKey( cp, "config", &val, &cnt ) == FALSE) {
	val = 0;
	cnt = 0;
    }
    loadSystemConfig(val, cnt);
    if ( !sysConfigValid ) return -1;

    // Use the kernel name specified by the user, or fetch the name
    // in the config table, or use the default if not specified.
    // Specifying a kernel name on the command line, or specifying
    // a non-default kernel name in the config file counts as
    // overriding the kernel, which causes the kernelcache not
    // to be used.

    gOverrideKernel = NO;
    if (( kernel = extractKernelName((char **)&cp) )) {
        strcpy( bootInfo->bootFile, kernel );
        gOverrideKernel = YES;
    } else {
        if ( getValueForKey( kKernelNameKey, &val, &cnt ) ) {
            strlcpy( bootInfo->bootFile, val, cnt+1 );
            if (strcmp( bootInfo->bootFile, kDefaultKernel ) != 0) {
                gOverrideKernel = YES;
            }
        } else {
            strcpy( bootInfo->bootFile, kDefaultKernel );
        }
    }

    cntRemaining = BOOT_STRING_LEN - 2;  // save 1 for NULL, 1 for space
    argP = bootArgs->CommandLine;

    // Get config table kernel flags, if not ignored.
    if (getValueForBootKey(cp, kIgnoreBootFileFlag, &val, &cnt) == TRUE ||
            getValueForKey( kKernelFlagsKey, &val, &cnt ) == FALSE) {
        val = "";
        cnt = 0;
    }
    configKernelFlags = (char *)malloc(cnt + 1);
    strlcpy(configKernelFlags, val, cnt + 1);

    if (processBootArgument(kBootUUIDKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, 0)) {
        // boot-uuid was set either on the command-line
        // or in the config file.
        uuidSet = YES;
    } else {
        if (GetFSUUID(bootInfo->bootFile, uuidStr) == 0) {
            verbose("Setting boot-uuid to: %s\n", uuidStr);
            copyArgument(kBootUUIDKey, uuidStr, strlen(uuidStr), &argP, &cntRemaining);
            uuidSet = YES;
        }
    }

    if (!processBootArgument(kRootDeviceKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, gRootDevice)) {
        cnt = 0;
        if ( getValueForKey( kBootDeviceKey, &val, &cnt)) {
            valueBuffer[0] = '*';
            cnt++;
            strlcpy(valueBuffer + 1, val, cnt);
            val = valueBuffer;
        } else {
            if (uuidSet) {
                val = "*uuid";
                cnt = 5;
            } else {
                // Don't set "rd=.." if there is no boot device key
                // and no UUID.
                val = "";
                cnt = 0;
            }
        } 
        if (cnt > 0) {
            copyArgument( kRootDeviceKey, val, cnt, &argP, &cntRemaining);
        }
        strlcpy( gRootDevice, val, (cnt + 1));
    }

    if (!processBootArgument(kPlatformKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, gPlatformName)) {
        getPlatformName(gPlatformName);
        copyArgument(kPlatformKey, gPlatformName, strlen(gPlatformName), &argP, &cntRemaining);
    }

    if (!getValueForBootKey(cp, kSafeModeFlag, &val, &cnt) &&
        !getValueForBootKey(configKernelFlags, kSafeModeFlag, &val, &cnt)) {
        if (gBootMode & kBootModeSafe) {
            copyArgument(0, kSafeModeFlag, strlen(kSafeModeFlag), &argP, &cntRemaining);
        }
    }

    // Store the merged kernel flags and boot args.

    cnt = strlen(configKernelFlags);
    if (cnt) {
        if (cnt > cntRemaining) {
            error("Warning: boot arguments too long, truncating\n");
            cnt = cntRemaining;
        }
        strncpy(argP, configKernelFlags, cnt);
        argP[cnt++] = ' ';
        cntRemaining -= cnt;
    }
    userCnt = strlen(cp);
    if (userCnt > cntRemaining) {
	error("Warning: boot arguments too long, truncating\n");
	userCnt = cntRemaining;
    }
    strncpy(&argP[cnt], cp, userCnt);
    argP[cnt+userCnt] = '\0';

    gVerboseMode = getValueForKey( kVerboseModeFlag, &val, &cnt ) ||
                   getValueForKey( kSingleUserModeFlag, &val, &cnt );

    gBootMode = ( getValueForKey( kSafeModeFlag, &val, &cnt ) ) ?
                kBootModeSafe : kBootModeNormal;

    if ( getValueForKey( kOldSafeModeFlag, &val, &cnt ) ) {
        gBootMode = kBootModeSafe;
    }

    if ( getValueForKey( kMKextCacheKey, &val, &cnt ) ) {
        strlcpy(gMKextName, val, cnt + 1);
    }

    free(configKernelFlags);
    free(valueBuffer);

    return 0;
}
Пример #7
0
int processBootOptions()
{
    const char *     cp  = gBootArgs;
    const char *     val = 0;
    const char *     kernel;
    int              cnt;
    int		     userCnt;
    int              cntRemaining;
    char *           argP;

    skipblanks( &cp );

    // Update the unit and partition number.

    if ( gBootVolume )
    {
        if ( gBootVolume->flags & kBVFlagForeignBoot )
        {
            readBootSector( gBootVolume->biosdev, gBootVolume->part_boff,
                            (void *) 0x7c00 );

            //
            // Setup edx, and signal intention to chain load the
            // foreign booter.
            //

            chainbootdev  = gBootVolume->biosdev;
            chainbootflag = 1;

            return 1;
        }

        bootArgs->kernDev &= ~((B_UNITMASK << B_UNITSHIFT ) |
                          (B_PARTITIONMASK << B_PARTITIONSHIFT));

        bootArgs->kernDev |= MAKEKERNDEV(    0,
 		         /* unit */      BIOS_DEV_UNIT(gBootVolume),
                        /* partition */ gBootVolume->part_no );
    }

    // Load config table specified by the user, or use the default.

    if (getValueForBootKey( cp, "config", &val, &cnt ) == FALSE) {
	val = 0;
	cnt = 0;
    }
    loadSystemConfig(val, cnt);
    if ( !sysConfigValid ) return -1;

    // Use the kernel name specified by the user, or fetch the name
    // in the config table, or use the default if not specified.
    // Specifying a kernel name on the command line, or specifying
    // a non-default kernel name in the config file counts as
    // overriding the kernel, which causes the kernelcache not
    // to be used.

    gOverrideKernel = NO;
    if (( kernel = extractKernelName((char **)&cp) )) {
        strcpy( bootArgs->bootFile, kernel );
        gOverrideKernel = YES;
    } else {
        if ( getValueForKey( kKernelNameKey, &val, &cnt ) ) {
            strlcpy( bootArgs->bootFile, val, cnt+1 );
            if (strcmp( bootArgs->bootFile, kDefaultKernel ) != 0) {
                gOverrideKernel = YES;
            }
        } else {
            strcpy( bootArgs->bootFile, kDefaultKernel );
        }
    }

    cntRemaining = BOOT_STRING_LEN - 2;  // save 1 for NULL, 1 for space

    // Check to see if we need to specify root device.
    // If user types "rd=.." on the boot line, it overrides
    // the boot device key in the boot arguments file.
    //
    argP = bootArgs->bootString;
    if ( getValueForBootKey( cp, kRootDeviceKey, &val, &cnt ) == FALSE &&
         getValueForKey( kRootDeviceKey, &val, &cnt ) == FALSE ) {
        if ( getValueForKey( kBootDeviceKey, &val, &cnt ) ) {
            strcpy( argP, "rd=*" );
            argP += 4;
            strlcpy( argP, val, cnt+1);
            cntRemaining -= cnt;
            argP += cnt;
            *argP++ = ' ';
        }
    }

    // Check to see if we should ignore saved kernel flags.
    if (getValueForBootKey(cp, kIgnoreBootFileFlag, &val, &cnt) == FALSE) {
        if (getValueForKey( kKernelFlagsKey, &val, &cnt ) == FALSE) {
	    val = 0;
	    cnt = 0;
        }
    }

    // Store the merged kernel flags and boot args.

    if (cnt > cntRemaining) {
	error("Warning: boot arguments too long, truncated\n");
	cnt = cntRemaining;
    }
    if (cnt) {
      strncpy(argP, val, cnt);
      argP[cnt++] = ' ';
    }
    cntRemaining = cntRemaining - cnt;
    userCnt = strlen(cp);
    if (userCnt > cntRemaining) {
	error("Warning: boot arguments too long, truncated\n");
	userCnt = cntRemaining;
    }
    strncpy(&argP[cnt], cp, userCnt);
    argP[cnt+userCnt] = '\0';

    gVerboseMode = getValueForKey( kVerboseModeFlag, &val, &cnt ) ||
                   getValueForKey( kSingleUserModeFlag, &val, &cnt );

    gBootMode = ( getValueForKey( kSafeModeFlag, &val, &cnt ) ) ?
                kBootModeSafe : kBootModeNormal;

    if ( getValueForKey( kPlatformKey, &val, &cnt ) ) {
        strlcpy(gPlatformName, val, cnt + 1);
    } else {
        strcpy(gPlatformName, "ACPI");
    }

    if ( getValueForKey( kMKextCacheKey, &val, &cnt ) ) {
        strlcpy(gMKextName, val, cnt + 1);
    }

    return 0;
}
Пример #8
0
//==========================================================================
// The 'main' function for the booter. Called by boot0 when booting
// from a block device, or by the network booter.
//
// arguments:
//   biosdev - Value passed from boot1/NBP to specify the device
//             that the booter was loaded from.
//
// If biosdev is kBIOSDevNetwork, then this function will return if
// booting was unsuccessful. This allows the PXE firmware to try the
// next boot device on its list.
void common_boot(int biosdev)
{
    int      status;
    char     *bootFile;
    unsigned long adler32;
    bool     quiet;
    bool     firstRun = true;
    bool     instantMenu;
    bool     rescanPrompt = false;
    unsigned int allowBVFlags = kBVFlagSystemVolume|kBVFlagForeignBoot;
    unsigned int denyBVFlags = kBVFlagEFISystem;

    // Set reminder to unload the PXE base code. Neglect to unload
    // the base code will result in a hang or kernel panic.
    gUnloadPXEOnExit = true;

    // Record the device that the booter was loaded from.
    gBIOSDev = biosdev & kBIOSDevMask;

    // Initialize boot info structure.
    initKernBootStruct();

	initBooterLog();

    // Setup VGA text mode.
    // Not sure if it is safe to call setVideoMode() before the
    // config table has been loaded. Call video_mode() instead.
#if DEBUG
    printf("before video_mode\n"); //Azi: this one is not printing... i remember it did.. check trunk.
#endif
    video_mode( 2 );  // 80x25 mono text mode.
#if DEBUG
    printf("after video_mode\n");
#endif

    // Scan and record the system's hardware information.
    scan_platform();

    // First get info for boot volume.
    scanBootVolumes(gBIOSDev, 0);
    bvChain = getBVChainForBIOSDev(gBIOSDev);
	//Azi: initialising gBIOSBootVolume & gBootVolume (Startup volume) for the first time.. i think!?
	// also, kDefaultPartitionKey is checked here, on selectBootVolume.
    setBootGlobals(bvChain);
	msglog("setBootGlobals:\n Default: %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBootVolume, gBootVolume->biosdev, gBootVolume->part_no, gBootVolume->flags);
    msglog(" bt(0,0): %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBIOSBootVolume, gBIOSBootVolume->biosdev, gBIOSBootVolume->part_no, gBIOSBootVolume->flags);

	// Boot Volume is set as Root at this point so, pointing to Extra, /Extra or bt(0,0)/Extra
	// is exactly the same.	Review bt(0,0)/bla bla paths......			(Reviewing...)
	
	//Azi: works as expected but... trying this because Kernel=mach_kernel doesn't work on a
	// override Boot.plist; this makes it impossible to override e.g. Kernel=bt(0,0)mach_kernel
	// on the main Boot.plist, when loading kernel from ramdisk btAliased.
	loadPrebootRAMDisk();
	
    // Load boot.plist config file
    //Azi: on this first check, boot.plist acts as both "booter config file"
    // and bootargs/options "carrier".*****
    status = loadSystemConfig(&bootInfo->bootConfig);

    if (getBoolForKey(kQuietBootKey, &quiet, &bootInfo->bootConfig) && quiet) {
        gBootMode |= kBootModeQuiet;
    }

    // Override firstRun to get to the boot menu instantly by setting "Instant Menu"=y in system config
    if (getBoolForKey(kInstantMenuKey, &instantMenu, &bootInfo->bootConfig) && instantMenu) {
        firstRun = false;
    }

	// Loading preboot ramdisk if exists.
//	loadPrebootRAMDisk(); //Azi: this needs to be done before load_all_modules()
	// because of btAlias...			(Reviewing...)

	// Intialize module system
	if (init_module_system())
	{
		load_all_modules();
	}

    // Disable rescan option by default
    gEnableCDROMRescan = false;

    // If we're loading the booter from optical media...			(Reviewing...)
	if (biosDevIsCDROM(gBIOSDev))
	{
		// ... ask the user for Rescan option by setting "Rescan Prompt"=y in system config...
		if (getBoolForKey(kRescanPromptKey, &rescanPrompt, &bootInfo->bootConfig) && rescanPrompt)
		{
	        gEnableCDROMRescan = promptForRescanOption();
	    }
		else // ... or enable it with Rescan=y in system config.
	    if (getBoolForKey(kRescanKey, &gEnableCDROMRescan, &bootInfo->bootConfig) && gEnableCDROMRescan)
		{
	        gEnableCDROMRescan = true;
	    }
	}

	//Azi: Is this a cdrom only thing?			(Reviewing...)
    // Enable touching a single BIOS device only if "Scan Single Drive"=y is set in system config.
    if (getBoolForKey(kScanSingleDriveKey, &gScanSingleDrive, &bootInfo->bootConfig) && gScanSingleDrive)
	{
		scanBootVolumes(gBIOSDev, &bvCount);
    }
	else
	{
		//Azi: scanDisks uses scanBootVolumes.
		scanDisks(gBIOSDev, &bvCount);
	}
	
    // Create a separated bvr chain using the specified filters.
    bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount);

    gBootVolume = selectBootVolume(bvChain);

//#if DEBUG
//printf
    msglog(":something...???\n Default: %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBootVolume, gBootVolume->biosdev, gBootVolume->part_no, gBootVolume->flags);
    msglog(" bt(0,0): %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBIOSBootVolume, gBIOSBootVolume->biosdev, gBIOSBootVolume->part_no, gBIOSBootVolume->flags);
//    getchar();
//#endif

    useGUI = true;
    // Override useGUI default
    getBoolForKey(kGUIKey, &useGUI, &bootInfo->bootConfig);

	// AutoResolution - Azi: default to false
	// http://forum.voodooprojects.org/index.php/topic,1227.0.html
	gAutoResolution = false;
	
	// Check if user enabled AutoResolution on Boot.plist...
	getBoolForKey(kAutoResolutionKey, &gAutoResolution, &bootInfo->bootConfig);
	
	// Patch the Video Bios with the extracted resolution, before initGui.
	if (gAutoResolution == true)
	{
		initAutoRes();
	}

    if (useGUI && initGUI())
	{
		// initGUI() returned with an error, disabling GUI.
		useGUI = false;
	}

    setBootGlobals(bvChain);
	msglog("setBootGlobals:\n Default: %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBootVolume, gBootVolume->biosdev, gBootVolume->part_no, gBootVolume->flags);
    msglog(" bt(0,0): %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBIOSBootVolume, gBIOSBootVolume->biosdev, gBIOSBootVolume->part_no, gBIOSBootVolume->flags);

    // Parse args, load and start kernel.
    while (1) {
        const char *val;
        int len;
        int trycache;
		long flags, cachetime, kerneltime, exttime, sleeptime, time;
        int ret = -1;
        void *binary = (void *)kLoadAddr;
        bool tryresume;
        bool tryresumedefault;
        bool forceresume;
		bool ignoreKC = false;

        // additional variable for testing alternate kernel image locations on boot helper partitions.
        char     bootFileSpec[512];
		
        // Initialize globals.

        sysConfigValid = false;
        gErrors        = false;

        status = getBootOptions(firstRun);
        firstRun = false;
        if (status == -1) continue;

		//Azi: test (gBootVolume == NULL) - so far Ok!
		// test with optical media again...?
		// Turn off any GUI elements, draw background and update VRAM.
		if ( bootArgs->Video.v_display == GRAPHICS_MODE )
		{
			gui.devicelist.draw = false;
			gui.bootprompt.draw = false;
			gui.menu.draw = false;
			gui.infobox.draw = false;
			gui.logo.draw = false;
			drawBackground();
			updateVRAM();
		}

		status = processBootOptions();

		//Azi: AutoResolution -  closing Vbios here without restoring, causes an allocation error,
		// if the user tries to boot, after a e.g."Can't find bla_kernel" msg.
		// Doing it on execKernel() instead.

		// Status == 1 means to chainboot
		if ( status ==	1 ) break;
		
		// Status == -1 means that gBootVolume is NULL. Config file is not mandatory anymore! 
		if ( status == -1 )
		{
			// gBootVolume == NULL usually means the user hit escape.			(Reviewing...)
			if (gBootVolume == NULL)
			{
				freeFilteredBVChain(bvChain);
				
				if (gEnableCDROMRescan)
					rescanBIOSDevice(gBIOSDev);
				
				bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount);
				setBootGlobals(bvChain);
				setupDeviceList(&bootInfo->themeConfig);
			}
			continue;
		}
		
        // Other status (e.g. 0) means that we should proceed with boot.

		// If cpu handles 64 bit instructions...
		if (platformCPUFeature(CPU_FEATURE_EM64T))
		{
			// use x86_64 kernel arch,...
			archCpuType = CPU_TYPE_X86_64;
		}
		else
		{
			// else use i386 kernel arch.
			archCpuType = CPU_TYPE_I386;
		}
		// If user override...
		if (getValueForKey(kArchKey, &val, &len, &bootInfo->bootConfig))
		{
			// matches i386...
			if (strncmp(val, "i386", 4) == 0)
			{
				// use i386 kernel arch.
				archCpuType = CPU_TYPE_I386;
			}
		}
		
		if (!getBoolForKey (kWakeKey, &tryresume, &bootInfo->bootConfig)) {
			tryresume = true;
			tryresumedefault = true;
		} else {
			tryresumedefault = false;
		}

		if (!getBoolForKey (kForceWakeKey, &forceresume, &bootInfo->bootConfig)) {
			forceresume = false;
		}
		
		if (forceresume) {
			tryresume = true;
			tryresumedefault = false;
		}
		
		while (tryresume) {
			const char *tmp;
			BVRef bvr;
			if (!getValueForKey(kWakeKeyImageKey, &val, &len, &bootInfo->bootConfig))
				val="/private/var/vm/sleepimage";
			
			// Do this first to be sure that root volume is mounted
			ret = GetFileInfo(0, val, &flags, &sleeptime);

			if ((bvr = getBootVolumeRef(val, &tmp)) == NULL)
				break;
			
			// Can't check if it was hibernation Wake=y is required
			if (bvr->modTime == 0 && tryresumedefault)
				break;
			
			if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat))
				break;
			
			if (!forceresume && ((sleeptime+3)<bvr->modTime)) {
				//Azi: no need for printf at this point - reminder
				printf ("Hibernate image is too old by %d seconds. Use ForceWake=y to override.\n",bvr->modTime-sleeptime);
				break;
			}
				
			HibernateBoot((char *)val);
			break;
		}

//Azi:kernelcache stuff
		bool patchKernel = false;
		getBoolForKey(kKPatcherKey, &patchKernel, &bootInfo->bootConfig);
		//Azi: avoiding having to use -f to ignore kernel cache
		//Azi: ignore kernel cache but still use kext cache (E/E.mkext & S/L/E.mkext). - explain...
		getBoolForKey(kUseKCKey, &ignoreKC, &bootInfo->bootConfig); // equivalent to UseKernelCache
		if (ignoreKC)
		{
			verbose("KC: cache ignored by user.\n");
			// make sure the damn thing get's zeroed, just in case... :)*
			bzero(gBootKernelCacheFile, sizeof(gBootKernelCacheFile));
		}
		else if (patchKernel) // to be moved..?
		{
			verbose("KC: kernel patcher enabled, ignore cache.\n");
			bzero(gBootKernelCacheFile, sizeof(gBootKernelCacheFile));
		}
		else if (getValueForKey(kKernelCacheKey, &val, &len, &bootInfo->bootConfig))
		{
            strlcpy(gBootKernelCacheFile, val, len + 1);
			verbose("KC: path set by user = %s\n", gBootKernelCacheFile);
			//Azi: bypass time check when user sets path ???
			// cache is still ignored if time doesn't match... (e.g. booter on usb stick)
        }
		else
		{
			// Reset cache name.
			bzero(gCacheNameAdler + 64, sizeof(gCacheNameAdler) - 64);
			
			// kextcache_main.c: Construct entry from UUID of boot volume...(reminder)
			// assemble ?string? to generate adler from...
//			sprintf(gCacheNameAdler + 64, "%s,%s", gRootDevice, bootInfo->bootFile); - OLD
			const char *ProductName = getStringForKey("SMproductname", &bootInfo->smbiosConfig);
			sprintf(gCacheNameAdler, ProductName); // well, at least the smbios.plist can be loaded this early...
			// to set/get "ProductName" this early, booter needs complete rewrite!!
			// see DHP's Revolution booter rework example!
		//	verbose("KC: gCacheNameAdler 1 = %s\n", gCacheNameAdler);
			//Azi: check the validity of this, e.g. on Helper Partitions
			sprintf(gCacheNameAdler + 64, "%s", "\\System\\Library\\CoreServices\\boot.efi");
		//	verbose("KC: gCacheNameAdler 2 = %s\n", gCacheNameAdler + 64);
			sprintf(gCacheNameAdler + (64 + 38), "%s", bootInfo->bootFile);
		//	verbose("KC: gCacheNameAdler 3 = %s\n", gCacheNameAdler + (64 + 38));

			// generate adler
			adler32 = Adler32((unsigned char *)gCacheNameAdler, sizeof(gCacheNameAdler));
		//	verbose("KC: Adler32 = %08X\n", adler32);
//Azi: no check for OS version here ?? - yes there is :)
			// append arch and/or adler (checksum) to kc path...
			if (gMacOSVersion[3] <= '5')
			{
				sprintf(gBootKernelCacheFile, "%s.%08lX", kCachePathTigerLeopard, adler32);
		//		verbose("KC: adler added to path = %s\n", gBootKernelCacheFile);
			}
			else
			{
				sprintf(gBootKernelCacheFile, "%s_%s.%08X", kCachePathSnowLion,
						(archCpuType == CPU_TYPE_I386) ? "i386" : "x86_64", adler32);
		//		verbose("KC: arch & adler added to path = %s\n", gBootKernelCacheFile);
			}
        }

        // Check for cache file.
		//Azi: trycache is done if...
        trycache = ( ( (gBootMode & kBootModeSafe) == 0) //... we're not booting in safe mode (-x arg),
					&& !gOverrideKernel // we're not overriding default kernel "name",
					&& (gBootFileType == kBlockDeviceType) // we're booting from local storage device,
					&& (gMKextName[0] == '\0') // "MKext Cache" key IS NOT in use, and
					&& (gBootKernelCacheFile[0] != '\0') ); // gBootKernelCacheFile is populated.
					// we could add the use of "kernelpatcher" to this bunch..??

//		verbose("Loading Darwin %s\n", gMacOSVersion); //Azi: move?? to getOSVersion? :)
		
        if (trycache) do
		{
			verbose("KC: checking kernel cache (system prelinked kernel)...\n");
            // if we haven't found the kernel yet, don't use the cache
            ret = GetFileInfo(NULL, bootInfo->bootFile, &flags, &kerneltime);
            if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat))
            {
				verbose("KC: no kernel found (shouldn't happen?!?)\n");
                trycache = 0; // ignore kernel cache...
                break;
            }
			verbose("KC: kerneltime = %d\n", kerneltime);
			
            ret = GetFileInfo(NULL, gBootKernelCacheFile, &flags, &cachetime);
            if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)
                || (cachetime < kerneltime))
            {
				if (cachetime <= 100) // confirm: 100 = inexistent path, -xxxxxxxxx = wrong name
				// not confirming... i also get -xxxxxxxxx with inexisting prelinked kernel
					verbose("KC: cachetime  = %d, kernel cache path/adler is incorrect, ignoring it. ??? \n",
							cachetime);
				else
					verbose("KC: cachetime  = %d, kernel cache is older than the kernel, ignoring it.\n",
							cachetime);
                trycache = 0;
                break;
            }
			verbose("KC: cachetime  = %d\n", cachetime);
			
            ret = GetFileInfo("/System/Library/", "Extensions", &flags, &exttime);
            if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)
                && (cachetime < exttime))
            {
				verbose("KC: exttime    = %d, kernel cache is older than S/L/E, ignoring it.\n", exttime);
                trycache = 0;
                break;
            }
			verbose("KC: exttime    = %d\n", exttime);
			
            if (kerneltime > exttime) // if S/L/E is older than the kernel...
            {
				verbose("KC: S/L/E is older than the kernel, matching exttime with kerneltime...\n");
                exttime = kerneltime;
            }
			verbose("KC: exttime +1 = %d\n", exttime + 1);
			
            if (cachetime != (exttime + 1))
            {
				verbose("KC: kernel cache time is diff from S/L/E time, ignoring it.\n");
                trycache = 0;
                break;
            }
			verbose("KC: kernel cache found and up to date, will be used.\n");

        } while (0);

        do
        {
			// Load kernel cache if not ignored.
            if (trycache)
            {
                bootFile = gBootKernelCacheFile;
                verbose("Loading kernel cache %s\n", bootFile);

                ret = LoadFile(bootFile);
                binary = (void *)kLoadAddr;

                if (ret >= 0)
                {
                    break;
                }
            }

            bootFile = bootInfo->bootFile;

            // Try to load kernel image from alternate locations on boot helper partitions.
            sprintf(bootFileSpec, "com.apple.boot.P/%s", bootFile);
            ret = GetFileInfo(NULL, bootFileSpec, &flags, &time); 
  	  	    if (ret == -1)
  	  	    {
				sprintf(bootFileSpec, "com.apple.boot.R/%s", bootFile);
				ret = GetFileInfo(NULL, bootFileSpec, &flags, &time); 
				if (ret == -1)
				{
					sprintf(bootFileSpec, "com.apple.boot.S/%s", bootFile);
					ret = GetFileInfo(NULL, bootFileSpec, &flags, &time); 
					if (ret == -1)
					{
						// No alternate location found, using the original kernel image path.
						strcpy(bootFileSpec, bootFile);
					}
				}
            }
            			
            verbose("Loading kernel %s\n", bootFileSpec);
            ret = LoadThinFatFile(bootFileSpec, &binary);
            if (ret <= 0 && archCpuType == CPU_TYPE_X86_64)
            {
				archCpuType = CPU_TYPE_I386;
				ret = LoadThinFatFile(bootFileSpec, &binary);				
            }
			
        } while (0);

        clearActivityIndicator();
/*#if DEBUG
        printf("Pausing...");
        sleep(8);
#endif
Azi: annoying stuff :P */
        if (ret <= 0)
		{
			printf("Can't find %s\n", bootFile);

			sleep(1);

            if (gBootFileType == kNetworkDeviceType) {
                // Return control back to PXE. Don't unload PXE base code.
                gUnloadPXEOnExit = false;
                break;
            }
        }
		else
		{
            // Won't return if successful.
            ret = ExecKernel(binary);
        }
    } // while (1)
    
    // chainboot
    if (status==1) {
		if (getVideoMode() == GRAPHICS_MODE) {	// if we are already in graphics-mode,
			setVideoMode(VGA_TEXT_MODE, 0);	// switch back to text mode
		}
    }
	
    if ((gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit)
	{
		nbpUnloadBaseCode();
    }
}