예제 #1
0
void initPlatform(int biosDevice)
{
	memset(&gPlatform, 0, sizeof(gPlatform));

	// Copied from cpu/dynamic_data.h to make printf work this early on.
#if DEBUG_CPU || DEBUG_PLATFORM
	extern void setVideoMode(int mode);
	setVideoMode(0); // Switch to VGA_TEXT_MODE
#endif

#if ENABLE_HPET
	enableHPET();
#endif

	gPlatform.RevoBootVersionInfo = strdup(REVOBOOT_VERSION_INFO);	// Example: "RevoBoot v1.0.04"

	_PLATFORM_DEBUG_DUMP("Booting with: %s\n", gPlatform.RevoBootVersionInfo);

#if AUTOMATIC_SSDT_PR_CREATION || DEBUG_TURBO_RATIOS
	uint8_t cpu = 0;
	uint8_t numberOfCores = STATIC_CPU_NumCores;

	// Zero out CPU core ratio limits.
	for (; cpu < numberOfCores; cpu++)
	{
		gPlatform.CPU.CoreTurboRatio[cpu] = 0; // Get updated later on in: i386/libsaio/Intel/cpu.c
	}
#endif

	// Jeroen: Initialized in cpu.c and used in ssdt_pr_generator.h
	gPlatform.CPU.NumberOfTurboRatios = 0;

	initCPUStruct();

	/*
	 * DHP: Booting with arch=i386 <i>and</i> setting this to CPU_TYPE_I386
	 * and setting the EFI_64_BIT directive in private_data to 0 allowed me 
	 * to boot in EFI32 mode. Even with my 64 bit configuration. Pretty sweet.
	 *
	 * Note to self: Get rid of gArchCPUType (global alarm) fast.
	 */

	gPlatform.ArchCPUType			= gArchCPUType = getArchCPUType();

	gPlatform.AddressWidth			= (gPlatform.ArchCPUType == CPU_TYPE_X86_64) ? 8 : 4;

	gPlatform.ACPI.Guid				= (EFI_GUID) EFI_ACPI_20_TABLE_GUID;

	gPlatform.SMBIOS.Guid			= (EFI_GUID) EFI_SMBIOS_TABLE_GUID;

#if INCLUDE_MPS_TABLE
	gPlatform.MPS.Guid				= (EFI_GUID) EFI_MPS_TABLE_GUID;
#endif // INCLUDE_MP_TABLE

	// Used in boot.c to verify the checksum (adler32) of pre-linked kernels.
	gPlatform.ModelID				= strdup(SMB_PRODUCT_NAME);

#if LOAD_MODEL_SPECIFIC_STATIC_DATA
	// Used in RevoBoot/i386/libsaio/ACPI/patcher.h, RevoBoot/i386/libsaio/efi.c
	// and RevoBoot/i386/libsaio/SMBIOS/static_data.h
	gPlatform.CommaLessModelID		= removeChar(strdup(gPlatform.ModelID), ',');
#endif

	// Determine system type based on product name. Used in
	// acpi/patcher.h to update FADT->Preferred_PM_Profile
	gPlatform.Type					= (strncmp(gPlatform.ModelID, "MacBook", 7) == 0) ? 2 : 1;

	// Are we supposted to have a Mobile CPU?
	if (gPlatform.Type == 2 && gPlatform.CPU.Mobile == false)
	{
		// Yes (based on the model identifier) but we either failed  
		// to detect a Mobile CPU, or we are using static CPU data.
		gPlatform.CPU.Mobile		= true;	// Will be initialized in cpu/cpu_dynamic.h (used in smbios/dynamic_data.h)
	}

#if (MAKE_TARGET_OS == LION)
	gPlatform.OSVersion				= strdup("10.7");
#elif (MAKE_TARGET_OS == MOUNTAIN_LION)
	gPlatform.OSVersion				= strdup("10.8");
#else // Snow Leopard
	gPlatform.OSVersion				= strdup("10.6");
#endif

	// _PLATFORM_DEBUG_DUMP("REVOBOOT_OS_TARGET: %d\n", REVOBOOT_OS_TARGET);

	gPlatform.OSType				= (int) MAKE_TARGET_OS;

	_PLATFORM_DEBUG_DUMP("gPlatform.OSType: %d\n", gPlatform.OSType);

	// Target OS setting from either make or config/settings.h
	// gPlatform.OSVersion[3]			= 0x34 + gPlatform.OSType;

	_PLATFORM_DEBUG_DUMP("gPlatform.OSVersion: %s\n", gPlatform.OSVersion);

	gPlatform.BIOSDevice			= (biosDevice & kBIOSDevMask);	// Device number masked with 0xFF.
	gPlatform.BootVolume			= NULL;	// Will be initialized in disk.c
	gPlatform.BootPartitionChain	= NULL;	// Will be initialized in sys.c
	gPlatform.RootVolume			= NULL;	// Will be initialized in disk.c (used in sys.c)

	gPlatform.RAM.SlotCount			= 0;	// Will be initialized further down (used in smbios/dynamic_data.h)

	gPlatform.KernelCachePath		= strdup(kKernelCachePath);	// Used in boot.c and driver.c

	_PLATFORM_DEBUG_DUMP("Kernel cache path: %s\n", gPlatform.KernelCachePath);

#if USE_STATIC_SMBIOS_DATA
	// We don't have to do anything when static SMBIOS data is used.
#elif OVERRIDE_DYNAMIC_MEMORY_DETECTION
	// Setup static STATIC_RAM_XXXX module info defined in config/settings.h
	const char * ramVendor[]		= STATIC_RAM_VENDORS;
	const char * ramPartNumber[]	= STATIC_RAM_PART_NUMBERS;
	const char * ramSerialNumber[]	= STATIC_RAM_SERIAL_NUMBERS;

#if DYNAMIC_RAM_OVERRIDE_SIZE
	int ramSize[]					= DYNAMIC_RAM_OVERRIDE_SIZES;
#endif

	int i = 0;

	// Loop through the static RAM vendors (might be different).
	for (; i < STATIC_RAM_SLOTS; i++)
	{
		gPlatform.RAM.SlotCount++;

		// We check for "N/A" so make sure you use that in config/settings.h
		if (strcmp(ramVendor[i], "N/A") != 0)
		{
			_PLATFORM_DEBUG_DUMP("Slot:%d, ", i); 

			gPlatform.RAM.MODULE[i].InUse			= true;
			gPlatform.RAM.MODULE[i].Type			= DYNAMIC_RAM_OVERRIDE_TYPE;
#if DYNAMIC_RAM_OVERRIDE_SIZE
			gPlatform.RAM.MODULE[i].Size			= ramSize[i];

			_PLATFORM_DEBUG_DUMP("Size:%d, ", gPlatform.RAM.MODULE[i].Size); 
#endif
			gPlatform.RAM.MODULE[i].Vendor			= ramVendor[i];
			gPlatform.RAM.MODULE[i].PartNumber		= ramPartNumber[i];
			gPlatform.RAM.MODULE[i].SerialNumber	= ramSerialNumber[i];

			_PLATFORM_DEBUG_DUMP("%s, %s, %s\n",
								 gPlatform.RAM.MODULE[i].Vendor,
								 gPlatform.RAM.MODULE[i].PartNumber,
								 gPlatform.RAM.MODULE[i].SerialNumber);
		}
		else
		{
			// Properly initialized for: smbios/dynamic_data.h which relies on it.
			gPlatform.RAM.MODULE[i].InUse			= false;
		}
	}

	_PLATFORM_DEBUG_DUMP("Static data for %d RAM BANKS used.\n", gPlatform.RAM.SlotCount);
#endif

	_PLATFORM_DEBUG_SLEEP(15);

	initKernelBootConfig();

#if (LOAD_MODEL_SPECIFIC_EFI_DATA)
	/*
	 * We need to call this much earlier in the boot process when static EFI data
	 * is read from: /Extra/EFI[MacModelNN.bin]. Otherwise LoadFile (load.c) fails.
	 */
	initPartitionChain();
#endif

	initEFITree();
}
예제 #2
0
파일: boot.c 프로젝트: AppleLife/RevoBoot
void boot(int biosdev)
{
    zeroBSS();
    mallocInit(0, 0, 0, mallocError);

#if MUST_ENABLE_A20
    // Enable A20 gate before accessing memory above 1 MB.
	if (fastEnableA20() != 0)
	{
		enableA20(); // Fast enable failed. Try legacy method.
	}
#endif

	bool	haveCABootPlist	= false;
	bool	quietBootMode	= true;

	void *fileLoadBuffer = (void *)kLoadAddr;

	char bootFile[256];
	char rootUUID[37];

	char * kernelFlags = NULL;

	const char * val;

	int length	= 0;
	int kernelFlagsLength = 0;

	bootFile[0] = '\0';
	rootUUID[0] = '\0';

#if PRE_LINKED_KERNEL_SUPPORT
	bool	mayUseKernelCache	= false;

	long flags, cachetime;
#endif

	initPlatform(biosdev);	// Passing on the boot drive.

#if DEBUG_STATE_ENABLED
	// Don't switch graphics mode / show boot logo when DEBUG is set to 1.
	printf("\ngArchCPUType (CPU): %s\n", (gArchCPUType == CPU_TYPE_X86_64) ? "x86_64" : "i386");
	sleep(3); // Silent sleep.
#else
	showBootLogo();
#endif

	// A bit ugly maybe, but this will be changed sometime soon.
	while (readKeyboardStatus())
	{
		int key = (bgetc() & 0xff);

		if ((key |= 0x20) == 'r')
		{
			gPlatform.BootRecoveryHD = true;
		}
	}

	initPartitionChain();

	#define loadCABootPlist() loadSystemConfig(&bootInfo->bootConfig)

	// Loading: /Library/Preferences/SystemConfiguration/com.apple.Boot.plist
	// TODO: Check if everything works <i>without</i> having this plist.
	if (loadCABootPlist() == STATE_SUCCESS)
	{
		_BOOT_DEBUG_DUMP("com.apple.Boot.plist located.\n");

		// Load successful. Change state accordantly.
		haveCABootPlist = true;	// Checked <i>before</i> calling key functions.

		// Check the value of <key>Kernel Flags</key> for stuff we are interested in.
		// Note: We need to know about: arch= and the boot flags: -s, -v, -f and -x

		if (getValueForKey(kKernelFlagsKey, &val, &kernelFlagsLength, &bootInfo->bootConfig))
		{
			// "Kernel Flags" key found. Check length to see if we have anything to work with.
			if (kernelFlagsLength)
			{
				kernelFlagsLength++;

				// Yes. Allocate memory for it and copy the kernel flags into it.
				kernelFlags = malloc(kernelFlagsLength);
				strlcpy(kernelFlags, val, kernelFlagsLength);

				// Is 'arch=<i386/x86_64>' specified as kernel flag?
				if (getValueForBootKey(kernelFlags, "arch", &val, &length)) //  && len >= 4)
				{
					gArchCPUType = (strncmp(val, "x86_64", 6) == 0) ? CPU_TYPE_X86_64 : CPU_TYPE_I386;

					_BOOT_DEBUG_DUMP("gArchCPUType (c.a.B.plist): %s\n",  (gArchCPUType == CPU_TYPE_X86_64) ? "x86_64" : "i386");
				}
				
				// Check for -v (verbose) and -s (single user mode) flags.
				gVerboseMode =	getValueForBootKey(kernelFlags, kVerboseModeFlag, &val, &length) || 
								getValueForBootKey(kernelFlags, kSingleUserModeFlag, &val, &length);
				
				if (gVerboseMode)
				{
#if DEBUG_BOOT == false
					setVideoMode(VGA_TEXT_MODE);
#endif
				}

				// Check for -x (safe) and -f (flush cache) flags.
				if (getValueForBootKey(kernelFlags, kSafeModeFlag, &val, &length) || 
					getValueForBootKey(kernelFlags, kIgnoreCachesFlag, &val, &length))
				{
					gBootMode = kBootModeSafe;
				}

				// Is 'boot-uuid=<value>' specified as kernel flag?
				if (getValueForBootKey(kernelFlags, kBootUUIDKey, &val, &length) && length == 36)
				{
					_BOOT_DEBUG_DUMP("Target boot-uuid=<%s>\n", val);

					// Yes. Copy its value into rootUUID.
					strlcpy(rootUUID, val, 37);
				}
				/* else
				{
					strlcpy(rootUUID, "3453E0E5-017B-38AD-A0AA-D0BBD8565D6", 37);
					_BOOT_DEBUG_DUMP("Target boot-uuid=<%s>\n", rootUUID);
				} */
			}
		}

#if PRE_LINKED_KERNEL_SUPPORT
		/* Look for 'Kernel Cache' key. */
		if (getValueForKey(kKernelCacheKey, &val, &length, &bootInfo->bootConfig))
		{
			_BOOT_DEBUG_DUMP("Kernel Cache set to: %s\n", val);

			// Key found. Check if the given filepath/name exists.
			if (length && GetFileInfo(NULL, val, &flags, &cachetime) == 0)
			{
				// File located. Init kernelCacheFile so that we can use it as boot file.
				gPlatform.KernelCachePath = strdup(val);

				// Set flag to inform the load process to skip parts of the code.
				gPlatform.KernelCacheSpecified = true;

				_BOOT_DEBUG_DUMP("kernelcache file found.\n");
			}

			_BOOT_DEBUG_ELSE_DUMP("Error: kernelcache file not found.\n");
		}

		// _BOOT_DEBUG_ELSE_DUMP("No 'Kernel Cache' key given.\n");
#endif
		/* Enable touching of a single BIOS device by setting 'Scan Single Drive' to yes.
		if (getBoolForKey(kScanSingleDriveKey, &gScanSingleDrive, &bootInfo->bootConfig) && gScanSingleDrive)
		{
			gScanSingleDrive = true;
		} */
	}
	else
	{
		_BOOT_DEBUG_DUMP("No com.apple.Boot.plist found.\n");
	}
	
	// Was a target drive (per UUID) specified in com.apple.Boot.plist?
	if (rootUUID[0] == '\0')
	{
		_BOOT_DEBUG_DUMP("No UUID specified in com.apple.Boot.plist\n");

		// No, so are we booting from a System Volume?
		if (gPlatform.BootVolume->flags & kBVFlagSystemVolume)
		{
			_BOOT_DEBUG_DUMP("Booting from a System Volume, getting UUID.\n");

			// Yes, then let's get the UUID.
			if (HFSGetUUID(gPlatform.BootVolume, rootUUID) == STATE_SUCCESS)
			{
				_BOOT_DEBUG_DUMP("Success [%s]\n", rootUUID);
			}
		}
		else // Booting from USB-stick or SDboot media.
		{
			_BOOT_DEBUG_DUMP("Booting from a Non System Volume, getting UUID.\n");

			// Get target System Volume and UUID in one go.
			BVRef rootVolume = getTargetRootVolume(rootUUID);

			if (rootVolume)
			{
				_BOOT_DEBUG_DUMP("Success [%s]\n", rootUUID);

				gPlatform.RootVolume = rootVolume;
			}
		}

		// This should never happen, but just to be sure.
		if (rootUUID[0] == '\0')
		{
			_BOOT_DEBUG_DUMP("Failed to get UUID for System Volume.\n");

			if (!gVerboseMode)
			{
				// Force verbose mode when we didn't find a UUID, so 
				// that people see what is going on in times of trouble.
				gVerboseMode = true;
			}
		}
	}

	/*
	 * At this stage we know exactly what boot mode we're in, and which disk to boot from
	 * any of which may or may not have been set/changed (in com.apple.Boot.plist) into a 
	 * non-default system setting and thus is this the place to update our EFI tree.
	 */

    updateEFITree(rootUUID);

	if (haveCABootPlist) // Check boolean before doing more time consuming tasks.
	{
		if (getBoolForKey(kQuietBootKey, &quietBootMode, &bootInfo->bootConfig) && !quietBootMode)
		{
			gBootMode = kBootModeNormal; // Reversed from: gBootMode |= kBootModeQuiet;
		}
	}

    // Parse args, load and start kernel.
    while (1)
    {
		// Initialize globals.

		sysConfigValid = 0;
		gErrors        = 0;

		int retStatus = -1;

		getAndProcessBootArguments(kernelFlags);

		// Initialize bootFile (defaults to: mach_kernel).
		strcpy(bootFile, bootInfo->bootFile);

#if PRE_LINKED_KERNEL_SUPPORT

		_BOOT_DEBUG_DUMP("gBootMode = %d\n", gBootMode);

		// Preliminary checks to prevent us from doing useless things.
		mayUseKernelCache = ((gBootMode & kBootModeSafe) == 0);

		_BOOT_DEBUG_DUMP("mayUseKernelCache = %s\n", mayUseKernelCache ? "true" : "false");

		/* 
		 * A pre-linked kernel, or kernelcache, requires you to have all essential kexts for your
		 * configuration, including FakeSMC.kext in: /System/Library/Extensions/ 
		 * Not in /Extra/Extensions/ because this directory will be ignored, completely when a 
		 * pre-linked kernel or kernelcache is used!
		 *
		 * Note: Not following this word of advise will render your system incapable of booting!
		 */
		
		if (mayUseKernelCache == false)
		{
			_BOOT_DEBUG_DUMP("Warning: kernelcache will be ignored!\n");

			// True when 'Kernel Cache' is set in com.apple.Boot.plist
			if (gPlatform.KernelCacheSpecified == true)
			{
				sprintf(bootFile, "%s", bootInfo->bootFile);
			}
		}
		else
		{
			// True when 'Kernel Cache' is set in com.apple.Boot.plist
			if (gPlatform.KernelCacheSpecified == true)
			{
				_BOOT_DEBUG_DUMP("kernelcache: %s\n", gPlatform.KernelCachePath);

				/*
				 * Starting with Lion, we can take a shortcut by simply pointing 
				 * the 'bootFile' to the kernel cache and we are done.
				 */

				sprintf(bootFile, "%s", gPlatform.KernelCachePath);
			}

			/*
			 * We might have been fired up from a USB thumbdrive (kickstart boot) and 
			 * thus we have to check the kernel cache path first (might not be there).
			 */

			else if (GetFileInfo(NULL, gPlatform.KernelCachePath, &flags, &cachetime) == 0)
			{

#if ((MAKE_TARGET_OS & LION) == LION) // Also for Mountain Lion, which has bit 2 set like Lion.

				_BOOT_DEBUG_DUMP("Checking for kernelcache...\n");

				if (GetFileInfo(gPlatform.KernelCachePath, (char *)kKernelCache, &flags, &cachetime) == 0)
				{
					sprintf(bootFile, "%s/%s", gPlatform.KernelCachePath, kKernelCache);

					_BOOT_DEBUG_DUMP("Kernelcache located.\n");
				}

				_BOOT_DEBUG_ELSE_DUMP("Failed to locate the kernelcache. Will load: %s!\n", bootInfo->bootFile);
			}

			_BOOT_DEBUG_ELSE_DUMP("Failed to locate the kernelcache (directory)!\n");
		}
#else // Not for (Mountain) Lion, go easy with the Snow Leopard.

				static char preLinkedKernelPath[128];
				static char adler32Key[PLATFORM_NAME_LEN + ROOT_PATH_LEN];

				unsigned long adler32 = 0;

				preLinkedKernelPath[0] = '\0';

				_BOOT_DEBUG_DUMP("Checking for pre-linked kernel...\n");

				// Zero out platform info (name and kernel root path).
				bzero(adler32Key, sizeof(adler32Key));
				
				// Construct key for the pre-linked kernel checksum (generated by adler32). 
				sprintf(adler32Key, gPlatform.ModelID);
				sprintf(adler32Key + PLATFORM_NAME_LEN, "%s", BOOT_DEVICE_PATH);
				sprintf(adler32Key + (PLATFORM_NAME_LEN + 38), "%s", bootInfo->bootFile);
				
				adler32 = Adler32((unsigned char *)adler32Key, sizeof(adler32Key));
				
				_BOOT_DEBUG_DUMP("adler32: %08X\n", adler32);
				
				// Create path to pre-linked kernel.
				sprintf(preLinkedKernelPath, "%s/%s_%s.%08lX", gPlatform.KernelCachePath, kKernelCache, 
						((gArchCPUType == CPU_TYPE_X86_64) ? "x86_64" : "i386"), adler32);

				// Check if this file exists.
				if ((GetFileInfo(NULL, preLinkedKernelPath, &flags, &cachetime) == 0) && ((flags & kFileTypeMask) == kFileTypeFlat))
				{
					_BOOT_DEBUG_DUMP("Pre-linked kernel cache located!\nLoading pre-linked kernel: %s\n", preLinkedKernelPath);
					
					// Returns -1 on error, or the actual filesize.
					if (LoadFile((const char *)preLinkedKernelPath))
					{
						retStatus = 1;
						fileLoadBuffer = (void *)kLoadAddr;
						bootFile[0] = 0;
					}

					_BOOT_DEBUG_ELSE_DUMP("Failed to load the pre-linked kernel. Will load: %s!\n", bootInfo->bootFile);
				}

				_BOOT_DEBUG_ELSE_DUMP("Failed to locate the pre-linked kernel!\n");
			}

			_BOOT_DEBUG_ELSE_DUMP("Failed to locate the cache directory!\n");
		}