Esempio n. 1
0
File: cpu.c Progetto: RemC/Chameleon
/*
 * Calculates the FSB and CPU frequencies using specific MSRs for each CPU
 * - multi. is read from a specific MSR. In the case of Intel, there is:
 *	   a max multi. (used to calculate the FSB freq.),
 *	   and a current multi. (used to calculate the CPU freq.)
 * - fsbFrequency = tscFrequency / multi
 * - cpuFrequency = fsbFrequency * multi
 */
void scan_cpu(PlatformInfo_t *p)
{
	uint64_t	tscFrequency, fsbFrequency, cpuFrequency;
	uint64_t	msr, flex_ratio;
	uint8_t		maxcoef, maxdiv, currcoef, bus_ratio_max, currdiv;
	const char	*newratio;
	int			len, myfsb;
	uint8_t		bus_ratio_min;
	uint32_t	max_ratio, min_ratio;
	
	max_ratio = min_ratio = myfsb = bus_ratio_min = 0;
	maxcoef = maxdiv = bus_ratio_max = currcoef = currdiv = 0;
	
	/* get cpuid values */
	do_cpuid(0x00000000, p->CPU.CPUID[CPUID_0]);
	do_cpuid(0x00000001, p->CPU.CPUID[CPUID_1]);
	do_cpuid(0x00000002, p->CPU.CPUID[CPUID_2]);
	do_cpuid(0x00000003, p->CPU.CPUID[CPUID_3]);
	do_cpuid2(0x00000004, 0, p->CPU.CPUID[CPUID_4]);
	do_cpuid(0x80000000, p->CPU.CPUID[CPUID_80]);
	if (p->CPU.CPUID[CPUID_0][0] >= 0x5) {		
		do_cpuid(5,  p->CPU.CPUID[CPUID_5]);        	
	}	
	if (p->CPU.CPUID[CPUID_0][0] >= 6) {
		do_cpuid(6, p->CPU.CPUID[CPUID_6]);		
	}
	if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 8) {
		do_cpuid(0x80000008, p->CPU.CPUID[CPUID_88]);
		do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);
	}
	else if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 1) {
		do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);
	}
	
#if DEBUG_CPU
	{
		int		i;
		printf("CPUID Raw Values:\n");
		for (i=0; i<CPUID_MAX; i++) {
			printf("%02d: %08x-%08x-%08x-%08x\n", i,
				   p->CPU.CPUID[i][0], p->CPU.CPUID[i][1],
				   p->CPU.CPUID[i][2], p->CPU.CPUID[i][3]);
		}
	}
#endif
	
	p->CPU.Vendor		= p->CPU.CPUID[CPUID_0][1];
	p->CPU.Signature	= p->CPU.CPUID[CPUID_1][0];
	p->CPU.Stepping		= bitfield(p->CPU.CPUID[CPUID_1][0], 3, 0);
	p->CPU.Model		= bitfield(p->CPU.CPUID[CPUID_1][0], 7, 4);
	p->CPU.Family		= bitfield(p->CPU.CPUID[CPUID_1][0], 11, 8);
	p->CPU.ExtModel		= bitfield(p->CPU.CPUID[CPUID_1][0], 19, 16);
	p->CPU.ExtFamily	= bitfield(p->CPU.CPUID[CPUID_1][0], 27, 20);
	
	p->CPU.Model += (p->CPU.ExtModel << 4);
	
	if (p->CPU.Vendor == CPUID_VENDOR_INTEL &&
		p->CPU.Family == 0x06 &&
		p->CPU.Model >= CPUID_MODEL_NEHALEM &&
		p->CPU.Model != CPUID_MODEL_ATOM		// MSR is *NOT* available on the Intel Atom CPU
		)
	{
		msr = rdmsr64(MSR_CORE_THREAD_COUNT);					// Undocumented MSR in Nehalem and newer CPUs
		p->CPU.NoCores		= bitfield((uint32_t)msr, 31, 16);	// Using undocumented MSR to get actual values
		p->CPU.NoThreads	= bitfield((uint32_t)msr, 15,  0);	// Using undocumented MSR to get actual values
	}
	else if (p->CPU.Vendor == CPUID_VENDOR_AMD)
	{
		p->CPU.NoThreads	= bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16);
		p->CPU.NoCores		= bitfield(p->CPU.CPUID[CPUID_88][2], 7, 0) + 1;
	}
	else
	{
		// Use previous method for Cores and Threads
		p->CPU.NoThreads	= bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16);
		p->CPU.NoCores		= bitfield(p->CPU.CPUID[CPUID_4][0], 31, 26) + 1;
	}
	
	/* get brand string (if supported) */
	/* Copyright: from Apple's XNU cpuid.c */
	if (p->CPU.CPUID[CPUID_80][0] > 0x80000004) {
		uint32_t	reg[4];
		char		str[128], *s;
		/*
		 * The brand string 48 bytes (max), guaranteed to
		 * be NULL terminated.
		 */
		do_cpuid(0x80000002, reg);
		bcopy((char *)reg, &str[0], 16);
		do_cpuid(0x80000003, reg);
		bcopy((char *)reg, &str[16], 16);
		do_cpuid(0x80000004, reg);
		bcopy((char *)reg, &str[32], 16);
		for (s = str; *s != '\0'; s++) {
			if (*s != ' ') break;
		}
		
		strlcpy(p->CPU.BrandString, s, sizeof(p->CPU.BrandString));
		
		if (!strncmp(p->CPU.BrandString, CPU_STRING_UNKNOWN, MIN(sizeof(p->CPU.BrandString), strlen(CPU_STRING_UNKNOWN) + 1))) {
			/*
			 * This string means we have a firmware-programmable brand string,
			 * and the firmware couldn't figure out what sort of CPU we have.
			 */
			p->CPU.BrandString[0] = '\0';
		}
	}
	
	/* setup features */
	if ((bit(23) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_MMX;
	}
	if ((bit(25) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE;
	}
	if ((bit(26) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE2;
	}
	if ((bit(0) & p->CPU.CPUID[CPUID_1][2]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE3;
	}
	if ((bit(19) & p->CPU.CPUID[CPUID_1][2]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE41;
	}
	if ((bit(20) & p->CPU.CPUID[CPUID_1][2]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE42;
	}
	if ((bit(29) & p->CPU.CPUID[CPUID_81][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_EM64T;
	}
	if ((bit(5) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_MSR;
	}
	//if ((bit(28) & p->CPU.CPUID[CPUID_1][3]) != 0) {
	if (p->CPU.NoThreads > p->CPU.NoCores) {
		p->CPU.Features |= CPU_FEATURE_HTT;
	}
	
	tscFrequency = measure_tsc_frequency();
	/* if usual method failed */
	if ( tscFrequency < 1000 )
	{
	tscFrequency = timeRDTSC() * 20;
	}
	fsbFrequency = 0;
	cpuFrequency = 0;
	
	if ((p->CPU.Vendor == CPUID_VENDOR_INTEL) && ((p->CPU.Family == 0x06) || (p->CPU.Family == 0x0f))) {
		int intelCPU = p->CPU.Model;
		if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0c) || (p->CPU.Family == 0x0f && p->CPU.Model >= 0x03)) {
			/* Nehalem CPU model */
			if (p->CPU.Family == 0x06 && (p->CPU.Model == CPU_MODEL_NEHALEM ||
										  p->CPU.Model == CPU_MODEL_FIELDS ||
										  p->CPU.Model == CPU_MODEL_DALES ||
										  p->CPU.Model == CPU_MODEL_DALES_32NM ||
										  p->CPU.Model == CPU_MODEL_WESTMERE ||
										  p->CPU.Model == CPU_MODEL_NEHALEM_EX ||
										  p->CPU.Model == CPU_MODEL_WESTMERE_EX ||
										  p->CPU.Model == CPU_MODEL_SANDYBRIDGE ||
										  p->CPU.Model == CPU_MODEL_JAKETOWN ||
										  p->CPU.Model == CPU_MODEL_IVYBRIDGE)) {
				msr = rdmsr64(MSR_PLATFORM_INFO);
				DBG("msr(%d): platform_info %08x\n", __LINE__, bitfield(msr, 31, 0));
				bus_ratio_max = bitfield(msr, 14, 8);
				bus_ratio_min = bitfield(msr, 46, 40); //valv: not sure about this one (Remarq.1)
				msr = rdmsr64(MSR_FLEX_RATIO);
				DBG("msr(%d): flex_ratio %08x\n", __LINE__, bitfield(msr, 31, 0));
				if (bitfield(msr, 16, 16)) {
					flex_ratio = bitfield(msr, 14, 8);
					/* bcc9: at least on the gigabyte h67ma-ud2h,
					 where the cpu multipler can't be changed to
					 allow overclocking, the flex_ratio msr has unexpected (to OSX)
					 contents.	These contents cause mach_kernel to
					 fail to compute the bus ratio correctly, instead
					 causing the system to crash since tscGranularity
					 is inadvertently set to 0.
					 */
					if (flex_ratio == 0) {
						/* Clear bit 16 (evidently the presence bit) */
						wrmsr64(MSR_FLEX_RATIO, (msr & 0xFFFFFFFFFFFEFFFFULL));
						msr = rdmsr64(MSR_FLEX_RATIO);
						verbose("Unusable flex ratio detected. Patched MSR now %08x\n", bitfield(msr, 31, 0));
					} else {
						if (bus_ratio_max > flex_ratio) {
							bus_ratio_max = flex_ratio;
						}
					}
				}
				
				if (bus_ratio_max) {
					fsbFrequency = (tscFrequency / bus_ratio_max);
				}
				//valv: Turbo Ratio Limit
				if ((intelCPU != 0x2e) && (intelCPU != 0x2f)) {
					msr = rdmsr64(MSR_TURBO_RATIO_LIMIT);
					cpuFrequency = bus_ratio_max * fsbFrequency;
					max_ratio = bus_ratio_max * 10;
				} else {
					cpuFrequency = tscFrequency;
				}
				if ((getValueForKey(kbusratio, &newratio, &len, &bootInfo->chameleonConfig)) && (len <= 4)) {
					max_ratio = atoi(newratio);
					max_ratio = (max_ratio * 10);
					if (len >= 3) max_ratio = (max_ratio + 5);
					
					verbose("Bus-Ratio: min=%d, max=%s\n", bus_ratio_min, newratio);
					
					// extreme overclockers may love 320 ;)
					if ((max_ratio >= min_ratio) && (max_ratio <= 320)) {
						cpuFrequency = (fsbFrequency * max_ratio) / 10;
						if (len >= 3) maxdiv = 1;
						else maxdiv = 0;
					} else {
						max_ratio = (bus_ratio_max * 10);
					}
				}
				//valv: to be uncommented if Remarq.1 didn't stick
				/*if (bus_ratio_max > 0) bus_ratio = flex_ratio;*/
				p->CPU.MaxRatio = max_ratio;
				p->CPU.MinRatio = min_ratio;
				
				myfsb = fsbFrequency / 1000000;
				verbose("Sticking with [BCLK: %dMhz, Bus-Ratio: %d]\n", myfsb, max_ratio);
				currcoef = bus_ratio_max;
			} else {
				msr = rdmsr64(MSR_IA32_PERF_STATUS);
				DBG("msr(%d): ia32_perf_stat 0x%08x\n", __LINE__, bitfield(msr, 31, 0));
				currcoef = bitfield(msr, 12, 8);
				/* Non-integer bus ratio for the max-multi*/
				maxdiv = bitfield(msr, 46, 46);
				/* Non-integer bus ratio for the current-multi (undocumented)*/
				currdiv = bitfield(msr, 14, 14);
				
				// This will always be model >= 3
				if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0e) || (p->CPU.Family == 0x0f))
				{
					/* On these models, maxcoef defines TSC freq */
					maxcoef = bitfield(msr, 44, 40);
				} else {
					/* On lower models, currcoef defines TSC freq */
					/* XXX */
					maxcoef = currcoef;
				}
				
				if (maxcoef) {
					if (maxdiv) {
						fsbFrequency = ((tscFrequency * 2) / ((maxcoef * 2) + 1));
					} else {
						fsbFrequency = (tscFrequency / maxcoef);
					}
					if (currdiv) {
						cpuFrequency = (fsbFrequency * ((currcoef * 2) + 1) / 2);
					} else {
						cpuFrequency = (fsbFrequency * currcoef);
					}
					DBG("max: %d%s current: %d%s\n", maxcoef, maxdiv ? ".5" : "",currcoef, currdiv ? ".5" : "");
				}
			}
		}
		/* Mobile CPU */
		if (rdmsr64(MSR_IA32_PLATFORM_ID) & (1<<28)) {
			p->CPU.Features |= CPU_FEATURE_MOBILE;
		}
	}
	else if ((p->CPU.Vendor == CPUID_VENDOR_AMD) && (p->CPU.Family == 0x0f))
	{
		switch(p->CPU.ExtFamily)
		{
			case 0x00: /* K8 */
				msr = rdmsr64(K8_FIDVID_STATUS);
				maxcoef = bitfield(msr, 21, 16) / 2 + 4;
				currcoef = bitfield(msr, 5, 0) / 2 + 4;
				break;
				
			case 0x01: /* K10 */
				msr = rdmsr64(K10_COFVID_STATUS);
				do_cpuid2(0x00000006, 0, p->CPU.CPUID[CPUID_6]);
				// EffFreq: effective frequency interface
				if (bitfield(p->CPU.CPUID[CPUID_6][2], 0, 0) == 1)
				{
					//uint64_t mperf = measure_mperf_frequency();
					uint64_t aperf = measure_aperf_frequency();
					cpuFrequency = aperf;
				}
				// NOTE: tsc runs at the maccoeff (non turbo)
				//			*not* at the turbo frequency.
				maxcoef	 = bitfield(msr, 54, 49) / 2 + 4;
				currcoef = bitfield(msr, 5, 0) + 0x10;
				currdiv = 2 << bitfield(msr, 8, 6);
				
				break;
				
			case 0x05: /* K14 */
				msr = rdmsr64(K10_COFVID_STATUS);
				currcoef  = (bitfield(msr, 54, 49) + 0x10) << 2;
				currdiv = (bitfield(msr, 8, 4) + 1) << 2;
				currdiv += bitfield(msr, 3, 0);
				
				break;
				
			case 0x02: /* K11 */
				// not implimented
				break;
		}
		
		if (maxcoef)
		{
			if (currdiv)
			{
				if (!currcoef) currcoef = maxcoef;
				if (!cpuFrequency)
					fsbFrequency = ((tscFrequency * currdiv) / currcoef);
				else
					fsbFrequency = ((cpuFrequency * currdiv) / currcoef);
				
				DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv);
			} else {
				if (!cpuFrequency)
					fsbFrequency = (tscFrequency / maxcoef);
				else 
					fsbFrequency = (cpuFrequency / maxcoef);
				DBG("%d\n", currcoef);
			}
		}
		else if (currcoef)
		{
			if (currdiv)
			{
				fsbFrequency = ((tscFrequency * currdiv) / currcoef);
				DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv);
			} else {
				fsbFrequency = (tscFrequency / currcoef);
				DBG("%d\n", currcoef);
			}
		}
		if (!cpuFrequency) cpuFrequency = tscFrequency;
	}
	
#if 0
	if (!fsbFrequency) {
		fsbFrequency = (DEFAULT_FSB * 1000);
		cpuFrequency = tscFrequency;
		DBG("0 ! using the default value for FSB !\n");
	}
#endif
	
	p->CPU.MaxCoef = maxcoef;
	p->CPU.MaxDiv = maxdiv;
	p->CPU.CurrCoef = currcoef;
	p->CPU.CurrDiv = currdiv;
	p->CPU.TSCFrequency = tscFrequency;
	p->CPU.FSBFrequency = fsbFrequency;
	p->CPU.CPUFrequency = cpuFrequency;
	
	// keep formatted with spaces instead of tabs
	DBG("CPU: Brand String:             %s\n",              p->CPU.BrandString);
    DBG("CPU: Vendor/Family/ExtFamily:  0x%x/0x%x/0x%x\n",  p->CPU.Vendor, p->CPU.Family, p->CPU.ExtFamily);
    DBG("CPU: Model/ExtModel/Stepping:  0x%x/0x%x/0x%x\n",  p->CPU.Model, p->CPU.ExtModel, p->CPU.Stepping);
    DBG("CPU: MaxCoef/CurrCoef:         0x%x/0x%x\n",       p->CPU.MaxCoef, p->CPU.CurrCoef);
    DBG("CPU: MaxDiv/CurrDiv:           0x%x/0x%x\n",       p->CPU.MaxDiv, p->CPU.CurrDiv);
    DBG("CPU: TSCFreq:                  %dMHz\n",           p->CPU.TSCFrequency / 1000000);
    DBG("CPU: FSBFreq:                  %dMHz\n",           p->CPU.FSBFrequency / 1000000);
    DBG("CPU: CPUFreq:                  %dMHz\n",           p->CPU.CPUFrequency / 1000000);
    DBG("CPU: NoCores/NoThreads:        %d/%d\n",           p->CPU.NoCores, p->CPU.NoThreads);
    DBG("CPU: Features:                 0x%08x\n",          p->CPU.Features);
#if DEBUG_CPU
	pause();
#endif
}
Esempio n. 2
0
BVRef selectBootVolume( BVRef chain )
{
  bool filteredChain = false;
	bool foundPrimary = false;
  BVRef bvr, bvr1 = 0, bvr2 = 0;
	
	if (chain->filtered) filteredChain = true;
	
	if (multiboot_partition_set)
		for ( bvr = chain; bvr; bvr = bvr->next )
			if ( bvr->part_no == multiboot_partition && bvr->biosdev == gBIOSDev ) 
				return bvr;
	
	/*
	 * Checking "Default Partition" key in system configuration - use format: hd(x,y) -
	 * to override the default selection.
	 */
  const char * val;
  char testStr[64];
  int cnt;

  if (getValueForKey(kDefaultPartition, &val, &cnt, &bootInfo->bootConfig) && cnt >= 7 && filteredChain)
  {
    for ( bvr = chain; bvr; bvr = bvr->next )
    {
      *testStr = '\0';
      if ( bvr->biosdev >= 0x80 && bvr->biosdev < 0x100 )
      {
        sprintf(testStr, "hd(%d,%d)", bvr->biosdev - 0x80, bvr->part_no);
        if (strcmp(testStr, val) == 0)
          return bvr;
      }
    }
  }

	/*
	 * Scannig the volume chain backwards and trying to find 
	 * a HFS+ volume with valid boot record signature.
	 * If not found any active partition then we will
	 * select this volume as the boot volume.
	 */
  for ( bvr = chain; bvr; bvr = bvr->next )
  {
    if ( bvr->flags & kBVFlagPrimary && bvr->biosdev == gBIOSDev ) foundPrimary = true;
    // zhell -- Undo a regression that was introduced from r491 to 492.
    // if gBIOSBootVolume is set already, no change is required
    if ( bvr->flags & (kBVFlagBootable|kBVFlagSystemVolume)
         && gBIOSBootVolume
         && (!filteredChain || (filteredChain && bvr->visible))
         && bvr->biosdev == gBIOSDev )
      bvr2 = bvr;
    // zhell -- if gBIOSBootVolume is NOT set, we use the "if" statement
    // from r491,
    if ( bvr->flags & kBVFlagBootable
         && ! gBIOSBootVolume
         && bvr->biosdev == gBIOSDev )
      bvr2 = bvr;
  }  

  
	/*
	 * Use the standrad method for selecting the boot volume.
	 */
	if (foundPrimary)
	{
		for ( bvr = chain; bvr; bvr = bvr->next )
		{
			if ( bvr->flags & kBVFlagNativeBoot && bvr->biosdev == gBIOSDev ) bvr1 = bvr;
			if ( bvr->flags & kBVFlagPrimary && bvr->biosdev == gBIOSDev )    bvr2 = bvr;
		}
  }

  bvr = bvr2 ? bvr2 :
        bvr1 ? bvr1 : chain;

  return bvr;
}
Esempio n. 3
0
int initGUI(void)
{
	int		val;
#ifdef EMBED_THEME
	config_file_t	*config;
	
	config = &bootInfo->themeConfig;
	if (ParseXMLFile((char *)__theme_plist, &config->dictionary) != 0) {
		return 1;
	}
#else
	int	len;
	char	dirspec[256];

	getValueForKey( "Theme", &theme_name, &len, &bootInfo->bootConfig );
	if ((strlen(theme_name) + 27) > sizeof(dirspec)) {
		return 1;
	}
	sprintf(dirspec, "/Extra/Themes/%s/theme.plist", theme_name);
	if (loadConfigFile(dirspec, &bootInfo->themeConfig) != 0) {
		return 1;
	}
#endif
	// parse display size parameters
	if (getIntForKey("screen_width", &val, &bootInfo->themeConfig)) {
		screen_params[0] = val;
	}
	if (getIntForKey("screen_height", &val, &bootInfo->themeConfig)) {
		screen_params[1] = val;
	}
	screen_params[2] = 32;

	// Initalizing GUI strucutre.
	bzero(&gui, sizeof(gui_t));
	
	// find best matching vesa mode for our requested width & height
	getGraphicModeParams(screen_params);

	// set our screen structure with the mode width & height
	gui.screen.width = screen_params[0];	
	gui.screen.height = screen_params[1];

	// load graphics otherwise fail and return
	if (loadGraphics() == 0) {
		loadThemeValues(&bootInfo->themeConfig, true);
		colorFont(&font_small, gui.screen.font_small_color);
		colorFont(&font_console, gui.screen.font_console_color);

		// create the screen & window buffers
		if (createBackBuffer(&gui.screen) == 0) {
			if (createWindowBuffer(&gui.screen) == 0) {
				if (createWindowBuffer(&gui.devicelist) == 0) {
					if (createWindowBuffer(&gui.bootprompt) == 0) {
						if (createWindowBuffer(&gui.infobox) == 0) {
							if (createWindowBuffer(&gui.menu) == 0) {							
								drawBackground();
								// lets copy the screen into the back buffer
								memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
								setVideoMode( GRAPHICS_MODE, 0 );
								gui.initialised = true;
								return 0;
							}
						}
					}
				}
			}
		}
	}
	return 1;
}
Esempio n. 4
0
/** From the origsmbios detected by getAddressOfSmbiosTable() to newsmbios whose entrypoint 
 * struct has been created by smbios_dry_run, update each table struct content of new smbios
 * int the new allocated table address of size newsmbios->tablelength.
 */
static void smbios_real_run(struct SMBEntryPoint * origsmbios, struct SMBEntryPoint * newsmbios)
{
	char *smbiostables;
	char *tablesptr, *newtablesptr;
	int origsmbiosnum;
	// bitmask of used handles
	uint8_t handles[8192]; 
	uint16_t nexthandle=0;
	int i, j;
	int tablespresent[256];
	bool do_auto=true;
        
        extern void dumpPhysAddr(const char * title, void * a, int len);

	bzero(tablespresent, sizeof(tablespresent));
	bzero(handles, sizeof(handles));

	getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig);
	
	newsmbios->dmi.tableAddress = (uint32_t)AllocateKernelMemory(newsmbios->dmi.tableLength);
	if (origsmbios) {
		smbiostables = (char *)origsmbios->dmi.tableAddress;
		origsmbiosnum = origsmbios->dmi.structureCount;
	} else {
		smbiostables = NULL;
		origsmbiosnum = 0;
	}
	tablesptr = smbiostables;
	newtablesptr = (char *)newsmbios->dmi.tableAddress;

        // if old smbios exists then update new smbios  with old smbios original content first
	if (smbiostables) {
		for (i=0; i<origsmbiosnum; i++) {
			struct smbios_table_header	*oldcur = (struct smbios_table_header *) tablesptr;
			struct smbios_table_header	*newcur = (struct smbios_table_header *) newtablesptr;
			char				*stringsptr;
			int				nstrings = 0;

			handles[(oldcur->handle) / 8] |= 1 << ((oldcur->handle) % 8);

                        // copy table length from old table to new table but not the old strings
			memcpy(newcur,oldcur, oldcur->length);

			tablesptr += oldcur->length;
			stringsptr = tablesptr;
			newtablesptr += oldcur->length;

                        // calculate the number of strings in the old content
			for (;tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++) {
				if (tablesptr[0] == 0) {
					nstrings++;
				}
			}
			if (tablesptr != stringsptr) {
				nstrings++;
			}
			tablesptr += 2;

                        // copy the old strings to new table
			memcpy(newtablesptr, stringsptr, tablesptr-stringsptr);

 			// point to next possible space for a string (deducting the second 0 char at the end)
			newtablesptr += tablesptr - stringsptr - 1;
                            if (nstrings == 0) { // if no string was found rewind to the first 0 char of the 0,0 terminator
				newtablesptr--;
			}

                        // now for each property in the table update the overrides if any (auto or user)
			for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
				const char	*str;
				int		size;
				int		num;
				char		altname[40];

				sprintf(altname, "%s_%d", smbios_properties[j].name, tablespresent[newcur->type] + 1);
				if (smbios_properties[j].table_type == newcur->type) {
					switch (smbios_properties[j].value_type) {
					case SMSTRING:
						if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
						    getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))
						{
							memcpy(newtablesptr, str, size);
							newtablesptr[size] = 0;
							newtablesptr += size + 1;
							*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
						} else if (do_auto && smbios_properties[j].auto_str) {
							str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);
							size = strlen(str);
							memcpy(newtablesptr, str, size);
							newtablesptr[size] = 0;
							newtablesptr += size + 1;
							*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
						}
						break;

					case SMOWORD:
						if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
						    getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))
						{
							int		k=0, t=0, kk=0;
							const char	*ptr = str;
							memset(((char*)newcur) + smbios_properties[j].offset, 0, 16);
							while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) {
								ptr++;
							}
							if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) {
								ptr += 2;
							}
							for (;ptr-str<size && *ptr && k<16;ptr++) {
								if (*ptr>='0' && *ptr<='9') {
									(t=(t<<4)|(*ptr-'0')),kk++;
								}
								if (*ptr>='a' && *ptr<='f') {
									(t=(t<<4)|(*ptr-'a'+10)),kk++;
								}
								if (*ptr>='A' && *ptr<='F') {
									(t=(t<<4)|(*ptr-'A'+10)),kk++;
								}
								if (kk == 2) {
									*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t;
									k++;
									kk = 0;
									t = 0;
								}
							}
						}
						break;

					case SMBYTE:
						if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||
						    getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))
						{
							*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
						} else if (do_auto && smbios_properties[j].auto_int) {
							*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);							
						}
						break;

					case SMWORD:
						if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||
						    getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))
						{
							*((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
						} else if (do_auto && smbios_properties[j].auto_int) {
							*((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
						}
						break;
					}
				}
			}
			if (nstrings == 0) {
				newtablesptr[0] = 0;
				newtablesptr++;
			}
			newtablesptr[0] = 0;
			newtablesptr++;
			tablespresent[newcur->type]++;
		}
	}

        // for each eventual complementary table not present in the original smbios, do the overrides
	for (i=0; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) {
		int	numnec = -1;
		char	buffer[40];

		sprintf(buffer, "SMtable%d", i);
		if (!getIntForKey(buffer, &numnec, &bootInfo->smbiosConfig)) {
			numnec = -1;
		}
		if (numnec == -1 && do_auto && smbios_table_descriptions[i].numfunc) {
			numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type);
		}
		while (tablespresent[smbios_table_descriptions[i].type] < numnec) {
			struct smbios_table_header	*newcur = (struct smbios_table_header *) newtablesptr;
			int				nstrings = 0;

			memset(newcur,0, smbios_table_descriptions[i].len);
			while (handles[(nexthandle)/8] & (1 << ((nexthandle) % 8))) {
				nexthandle++;
			}
			newcur->handle = nexthandle;
			handles[nexthandle / 8] |= 1 << (nexthandle % 8);
			newcur->type = smbios_table_descriptions[i].type;
			newcur->length = smbios_table_descriptions[i].len;
			newtablesptr += smbios_table_descriptions[i].len;
			for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
				const char	*str;
				int		size;
				int		num;
				char		altname[40];

				sprintf(altname, "%s_%d", smbios_properties[j].name, tablespresent[newcur->type] + 1);
				if (smbios_properties[j].table_type == newcur->type) {
					switch (smbios_properties[j].value_type) {
					case SMSTRING:
						if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
						    getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))
						{
							memcpy(newtablesptr, str, size);
							newtablesptr[size] = 0;
							newtablesptr += size + 1;
							*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
						} else if (do_auto && smbios_properties[j].auto_str) {
							str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);
							size = strlen(str);
							memcpy(newtablesptr, str, size);
							newtablesptr[size] = 0;
							newtablesptr += size + 1;
							*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
						}
						break;

					case SMOWORD:
						if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
						    getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))
						{
							int		k=0, t=0, kk=0;
							const char	*ptr = str;

							memset(((char*)newcur) + smbios_properties[j].offset, 0, 16);
							while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) {
								ptr++;
							}
							if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) {
								ptr += 2;
							}
							for (;ptr-str<size && *ptr && k<16;ptr++) {
								if (*ptr>='0' && *ptr<='9') {
									(t=(t<<4)|(*ptr-'0')),kk++;
								}
								if (*ptr>='a' && *ptr<='f') {
									(t=(t<<4)|(*ptr-'a'+10)),kk++;
								}
								if (*ptr>='A' && *ptr<='F') {
									(t=(t<<4)|(*ptr-'A'+10)),kk++;
								}
								if (kk == 2) {
									*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t;
									k++;
									kk = 0;
									t = 0;
								}
							}
						}
						break;
						
					case SMBYTE:
						if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||
						    getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))
						{
							*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
						} else if (do_auto && smbios_properties[j].auto_int) {
							*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
						}
						break;
						
					case SMWORD:
						if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||
						    getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))
						{
							*((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
						} else if (do_auto && smbios_properties[j].auto_int) {
							*((uint16_t*)(((char*)newcur)+smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
						}
						break;
					}
				}
			}
			if (nstrings == 0) {
				newtablesptr[0] = 0;
				newtablesptr++;
			}
			newtablesptr[0] = 0;
			newtablesptr++;
			tablespresent[smbios_table_descriptions[i].type]++;
		}
	}

        // calculate new checksums
	newsmbios->dmi.checksum = 0;
	newsmbios->dmi.checksum = 256 - checksum8(&newsmbios->dmi, sizeof(newsmbios->dmi));
	newsmbios->checksum = 0;
	newsmbios->checksum = 256 - checksum8(newsmbios, sizeof(*newsmbios));
	verbose("Patched DMI Table\n");
}
Esempio n. 5
0
void
smbios_real_run (struct SMBEntryPoint * origsmbios,
				 struct SMBEntryPoint * newsmbios)
{
	char *smbiostables=0;
	char *tablesptr, *newtablesptr;
	int origsmbiosnum=0;
	// bitmask of used handles
	uint8_t handles[8192]; 
	uint16_t nexthandle=0;
	int i, j;
	int tablespresent[256];
	BOOL do_auto=1;
	
	getBoolForKey("SMBIOSdefaults",&do_auto,&bootInfo->bootConfig);
	
	for (i=0;i<256;i++)
		tablespresent[i]=0;
	
	memset (handles,0,8192);
	newsmbios->dmi.tableAddress=(uint32_t)AllocateKernelMemory(newsmbios->dmi.tableLength);
	if (origsmbios)
    {
		smbiostables=(char *) origsmbios->dmi.tableAddress;
		origsmbiosnum=origsmbios->dmi.structureCount;
    }
	tablesptr=smbiostables;
	newtablesptr=(char *) newsmbios->dmi.tableAddress;
	if (smbiostables)
		for (i=0;i<origsmbiosnum;i++)
		{
			struct smbios_table_header *oldcur
			=(struct smbios_table_header *) tablesptr,
			*newcur=(struct smbios_table_header *) newtablesptr;
			char *stringsptr;
			int nstrings=0;
			
			handles[(oldcur->handle)/8]|=1<<((oldcur->handle)%8);
			
			memcpy (newcur,oldcur, oldcur->length);
			
			tablesptr+=oldcur->length;
			stringsptr=tablesptr;
			newtablesptr+=oldcur->length;
			for (;tablesptr[0]!=0 || tablesptr[1]!=0;tablesptr++)
				if (tablesptr[0]==0)
					nstrings++;
			if (tablesptr!=stringsptr)
				nstrings++;
			tablesptr+=2;
			memcpy (newtablesptr,stringsptr,tablesptr-stringsptr);
			//point to next possible space for a string
			newtablesptr+=tablesptr-stringsptr-1;
			if (nstrings==0)
				newtablesptr--;
			for (j=0;j<sizeof (smbios_properties)/sizeof(smbios_properties[0]);
				 j++)
			{
				const char *str;
				int size;
				int num;
				char altname[40];
				sprintf (altname, "%s_%d",smbios_properties[j].name,
						 tablespresent[newcur->type]+1);				
				
				if (smbios_properties[j].table_type==newcur->type)
					switch (smbios_properties[j].value_type)
				{
					case SMSTRING:
						if (getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig)
							||getValueForKey(smbios_properties[j].name,&str, &size, &bootInfo->smbiosConfig))
						{
							memcpy (newtablesptr, str,size);
							newtablesptr[size]=0;
							newtablesptr+=size+1;
							*((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))=++nstrings;
						}
						else if (do_auto && smbios_properties[j].auto_str)
						{
							str=smbios_properties[j].auto_str(smbios_properties[j].name,tablespresent[newcur->type]);
							size=strlen (str);
							memcpy (newtablesptr, str,size);
							newtablesptr[size]=0;
							newtablesptr+=size+1;
							*((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))=++nstrings;
						}
						
						break;
						
					case SMOWORD:
						if (getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig)
							||getValueForKey(smbios_properties[j].name,&str, &size, &bootInfo->smbiosConfig))
						{
							int k=0, t=0, kk=0;
							const char *ptr=str;
							memset(((char*)newcur)+smbios_properties[j].offset, 0, 16);
							while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n'))
								ptr++;
							if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X'))
								ptr+=2;
							for (;ptr-str<size && *ptr && k<16;ptr++)
							{
								if (*ptr>='0' && *ptr<='9')
									(t=(t<<4)|(*ptr-'0')),kk++;
								if (*ptr>='a' && *ptr<='f')
									(t=(t<<4)|(*ptr-'a'+10)),kk++;
								if (*ptr>='A' && *ptr<='F')
									(t=(t<<4)|(*ptr-'A'+10)),kk++;
								if (kk==2)
								{
									*((uint8_t*)(((char*)newcur)+smbios_properties[j].offset+k))=t;
									k++;
									kk=0;
									t=0;
								}
							}
						}
						break;
						
					case SMBYTE:
						if (getIntForKey(altname,&num,&bootInfo->smbiosConfig)
							||getIntForKey(smbios_properties[j].name,&num,&bootInfo->smbiosConfig))
							*((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))=num;
						else if (do_auto && smbios_properties[j].auto_int)
							*((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))
							=smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);							
						break;
						
					case SMWORD:
						if (getIntForKey(altname,&num,&bootInfo->smbiosConfig)
							||getIntForKey(smbios_properties[j].name,&num,&bootInfo->smbiosConfig))
							*((uint16_t*)(((char*)newcur)+smbios_properties[j].offset))=num;
						else if (do_auto && smbios_properties[j].auto_int)
							*((uint16_t*)(((char*)newcur)+smbios_properties[j].offset))
							=smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
						break;
				}
			}
			if (nstrings==0)
			{
				newtablesptr[0]=0;
				newtablesptr++;
			}
			newtablesptr[0]=0;
			newtablesptr++;
			tablespresent[newcur->type]++;
		}
	for (i=0;i<sizeof (smbios_table_descriptions)
		 /sizeof(smbios_table_descriptions[0]);i++)
	{
		int numnec=-1;
		char buffer[40];
		sprintf (buffer, "SMtable%d", i);
		if (!getIntForKey(buffer,&numnec,&bootInfo->smbiosConfig))
			numnec=-1;
		if (numnec==-1 && do_auto && smbios_table_descriptions[i].numfunc)
			numnec=smbios_table_descriptions[i].numfunc (smbios_table_descriptions[i].type);
		
		while (tablespresent[smbios_table_descriptions[i].type]<numnec)
		{
			struct smbios_table_header *newcur=(struct smbios_table_header *) newtablesptr;
			int nstrings=0;
			
			memset (newcur,0, smbios_table_descriptions[i].len);
			while (handles[(nexthandle)/8]&(1<<((nexthandle)%8)))
				nexthandle++;
			newcur->handle=nexthandle;
			handles[nexthandle/8]|=1<<(nexthandle%8);
			newcur->type=smbios_table_descriptions[i].type;
			newcur->length=smbios_table_descriptions[i].len;
			newtablesptr+=smbios_table_descriptions[i].len;
			for (j=0;j<sizeof (smbios_properties)/sizeof(smbios_properties[0]);
				 j++)
			{
				const char *str;
				int size;
				int num;
				char altname[40];
				sprintf (altname, "%s_%d",smbios_properties[j].name,
						 tablespresent[newcur->type]+1);				
				
				if (smbios_properties[j].table_type==newcur->type)
					switch (smbios_properties[j].value_type)
				{
					case SMSTRING:
						if (getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig)
							||getValueForKey(smbios_properties[j].name,&str, &size, &bootInfo->smbiosConfig))
						{
							memcpy (newtablesptr, str,size);
							newtablesptr[size]=0;
							newtablesptr+=size+1;
							*((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))=++nstrings;
						}
						else if (do_auto && smbios_properties[j].auto_str)
						{
							str=smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);
							size=strlen (str);
							memcpy (newtablesptr, str,size);
							newtablesptr[size]=0;
							newtablesptr+=size+1;
							*((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))=++nstrings;
						}						
						break;
						
					case SMOWORD:
						if (getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig)
							||getValueForKey(smbios_properties[j].name,&str, &size, &bootInfo->smbiosConfig))
						{
							int k=0, t=0, kk=0;
							const char *ptr=str;
							memset(((char*)newcur)+smbios_properties[j].offset, 0, 16);
							while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n'))
								ptr++;
							if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X'))
								ptr+=2;
							for (;ptr-str<size && *ptr && k<16;ptr++)
							{
								if (*ptr>='0' && *ptr<='9')
									(t=(t<<4)|(*ptr-'0')),kk++;
								if (*ptr>='a' && *ptr<='f')
									(t=(t<<4)|(*ptr-'a'+10)),kk++;
								if (*ptr>='A' && *ptr<='F')
									(t=(t<<4)|(*ptr-'A'+10)),kk++;
								if (kk==2)
								{
									*((uint8_t*)(((char*)newcur)+smbios_properties[j].offset+k))=t;
									k++;
									kk=0;
									t=0;
								}
							}
						}
						break;
						
					case SMBYTE:
						if (getIntForKey(altname,&num,&bootInfo->smbiosConfig)
							||getIntForKey(smbios_properties[j].name,&num,&bootInfo->smbiosConfig))
							*((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))=num;
						else if (do_auto && smbios_properties[j].auto_int)
							*((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))
							=smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
						break;
						
					case SMWORD:
						if (getIntForKey(altname,&num,&bootInfo->smbiosConfig)
							||getIntForKey(smbios_properties[j].name,&num,&bootInfo->smbiosConfig))
							*((uint16_t*)(((char*)newcur)+smbios_properties[j].offset))=num;
						else if (do_auto && smbios_properties[j].auto_int)
							*((uint16_t*)(((char*)newcur)+smbios_properties[j].offset))
							=smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
						break;
				}
			}
			if (nstrings==0)
			{
				newtablesptr[0]=0;
				newtablesptr++;
			}
			newtablesptr[0]=0;
			newtablesptr++;
			tablespresent[smbios_table_descriptions[i].type]++;
		}
	}
	newsmbios->dmi.checksum=0;
	newsmbios->dmi.checksum=256-checksum8 (&newsmbios->dmi,sizeof (newsmbios->dmi));
	newsmbios->checksum=0;
	newsmbios->checksum=256-checksum8 (newsmbios,sizeof (*newsmbios));
	verbose("Patched DMI Table.\n");
}
int getBootOptions(bool firstRun)
{
	int     i;
	int     key;
	int     nextRow;
	int     timeout;
	int     bvCount;
	BVRef   bvr;
	BVRef   menuBVR;
	bool    showPrompt, newShowPrompt, isCDROM;

	// Initialize default menu selection entry.
	gBootVolume = menuBVR = selectBootVolume(bvChain);

	if (biosDevIsCDROM(gBIOSDev)) {
		isCDROM = true;
	} else {
		isCDROM = false;
	}

	// ensure we're in graphics mode if gui is setup
	if (firstRun && gui.initialised && bootArgs->Video.v_display == VGA_TEXT_MODE)
	{
		setVideoMode(GRAPHICS_MODE, 0);
	}

	// Clear command line boot arguments
	clearBootArgs();

	// Allow user to override default timeout.
	if (multiboot_timeout_set) {
		timeout = multiboot_timeout;
	} else if (!getIntForKey(kTimeoutKey, &timeout, &bootInfo->chameleonConfig)) {
		/*  If there is no timeout key in the file use the default timeout
		    which is different for CDs vs. hard disks.  However, if not booting
		    a CD and no config file could be loaded set the timeout
		    to zero which causes the menu to display immediately.
		    This way, if no partitions can be found, that is the disk is unpartitioned
		    or simply cannot be read) then an empty menu is displayed.
		    If some partitions are found, for example a Windows partition, then
		    these will be displayed in the menu as foreign partitions.
		 */
		if (isCDROM) {
			timeout = kCDBootTimeout;
		} else {
			timeout = sysConfigValid ? kBootTimeout : 0;
		}
	}

	if (timeout < 0) {
		gBootMode |= kBootModeQuiet;
	}

	// If the user is holding down a modifier key, enter safe mode.
	if ((readKeyboardShiftFlags() & 0x0F) != 0) {
		gBootMode |= kBootModeSafe;
	}

	// Checking user pressed keys
	bool f8press = false, spress = false, vpress = false;
	while (readKeyboardStatus()) {
		key = bgetc ();
		if (key == 0x4200) f8press = true;
		if ((key & 0xff) == 's' || (key & 0xff) == 'S') spress = true;
		if ((key & 0xff) == 'v' || (key & 0xff) == 'V') vpress = true;
	}
	// If user typed F8, abort quiet mode, and display the menu.
	if (f8press) {
		gBootMode &= ~kBootModeQuiet;
		timeout = 0;
	}
	// If user typed 'v' or 'V', boot in verbose mode.
	if ((gBootMode & kBootModeQuiet) && firstRun && vpress) {
		addBootArg(kVerboseModeFlag);
	}
	// If user typed 's' or 'S', boot in single user mode.
	if ((gBootMode & kBootModeQuiet) && firstRun && spress) {
		addBootArg(kSingleUserModeFlag);
	}

	if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
		setCursorPosition(0, 0, 0);
		clearScreenRows(0, kScreenLastRow);
		if (!(gBootMode & kBootModeQuiet)) {
			// Display banner and show hardware info.
			printf(bootBanner, (bootInfo->convmem + bootInfo->extmem) / 1024);
			printf(getVBEInfoString());
		}
		changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0);
		verbose("Scanning device %x...", gBIOSDev);
	}

	// When booting from CD, default to hard drive boot when possible. 
	if (isCDROM && firstRun) {
		const char *val;
		char *prompt = NULL;
		char *name = NULL;
		int cnt;
		int optionKey;

		if (getValueForKey(kCDROMPromptKey, &val, &cnt, &bootInfo->chameleonConfig)) {
			prompt = malloc(cnt + 1);
			strncat(prompt, val, cnt);
		} else {
			name = malloc(80);
			getBootVolumeDescription(gBootVolume, name, 79, false);
			prompt = malloc(256);
			sprintf(prompt, "Press any key to start up from %s, or press F8 to enter startup options.", name);
			free(name);
		}

		if (getIntForKey( kCDROMOptionKey, &optionKey, &bootInfo->chameleonConfig )) {
			// The key specified is a special key.
		} else {
			// Default to F8.
			optionKey = 0x4200;
		}

		// If the timeout is zero then it must have been set above due to the
		// early catch of F8 which means the user wants to set boot options
		// which we ought to interpret as meaning he wants to boot the CD.
		if (timeout != 0) {
			key = countdown(prompt, kMenuTopRow, timeout);
		} else {
			key = optionKey;
		}

		if (prompt != NULL) {
			free(prompt);
		}

		clearScreenRows( kMenuTopRow, kMenuTopRow + 2 );

		// Hit the option key ?
		if (key == optionKey) {
			gBootMode &= ~kBootModeQuiet;
			timeout = 0;
		} else {
			key = key & 0xFF;

			// Try booting hard disk if user pressed 'h'
			if (biosDevIsCDROM(gBIOSDev) && key == 'h') {
				BVRef bvr;

				// Look at partitions hosting OS X other than the CD-ROM
				for (bvr = bvChain; bvr; bvr=bvr->next) {
					if ((bvr->flags & kBVFlagSystemVolume) && bvr->biosdev != gBIOSDev) {
						gBootVolume = bvr;
					}
				}
			}
			goto done;
		}
	}

	if (gBootMode & kBootModeQuiet) {
		// No input allowed from user.
		goto done;
	}

	if (firstRun && timeout > 0 && countdown("Press any key to enter startup options.", kMenuTopRow, timeout) == 0) {
		// If the user is holding down a modifier key,
		// enter safe mode.
		if ((readKeyboardShiftFlags() & 0x0F) != 0) {
			gBootMode |= kBootModeSafe;
		}
		goto done;
	}

	if (gDeviceCount) {
		// Allocate memory for an array of menu items.
		menuItems = malloc(sizeof(MenuItem) * gDeviceCount);
		if (menuItems == NULL) {
			goto done;
		}

		// Associate a menu item for each BVRef.
		for (bvr=bvChain, i=gDeviceCount-1, selectIndex=0; bvr; bvr=bvr->next) {
			if (bvr->visible) {
				getBootVolumeDescription(bvr, menuItems[i].name, sizeof(menuItems[i].name) - 1, true);
				menuItems[i].param = (void *) bvr;
				if (bvr == menuBVR) {
					selectIndex = i;
				}
				i--;
			}
		}
	}

	if (bootArgs->Video.v_display != VGA_TEXT_MODE) {
		// redraw the background buffer
		gui.logo.draw = true;
		drawBackground();
		gui.devicelist.draw = true;
		gui.redraw = true;
		if (!(gBootMode & kBootModeQuiet)) {
 
			// Check if "Boot Banner"=N switch is present in config file.
			getBoolForKey(kBootBannerKey, &showBootBanner, &bootInfo->chameleonConfig); 
			if (showBootBanner) {
				// Display banner and show hardware info.
				gprintf(&gui.screen, bootBanner + 1, (bootInfo->convmem + bootInfo->extmem) / 1024);
			}

			// redraw background
			memcpy(gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4);
		}
	} else {
		// Clear screen and hide the blinking cursor.
		clearScreenRows(kMenuTopRow, kMenuTopRow + 2);
		changeCursor(0, kMenuTopRow, kCursorTypeHidden, 0);
	}

	nextRow = kMenuTopRow;
	showPrompt = true;

	if (gDeviceCount) {
		if( bootArgs->Video.v_display == VGA_TEXT_MODE ) {
			printf("Use \30\31 keys to select the startup volume.");
		}
		showMenu( menuItems, gDeviceCount, selectIndex, kMenuTopRow + 2, kMenuMaxItems );
		nextRow += MIN( gDeviceCount, kMenuMaxItems ) + 3;
	}

	// Show the boot prompt.
	showPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot);
	showBootPrompt( nextRow, showPrompt );
	
	do {
		if (bootArgs->Video.v_display != VGA_TEXT_MODE) {
			// redraw background
			memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
			// reset cursor co-ords
			gui.debug.cursor = pos( gui.screen.width - 160 , 10 );
		}
		key = getchar();
		updateMenu( key, (void **) &menuBVR );
		newShowPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot);

		if (newShowPrompt != showPrompt) {
			showPrompt = newShowPrompt;
			showBootPrompt( nextRow, showPrompt );
		}

		if (showPrompt) {
			updateBootArgs(key);
		}

		switch (key) {
		case kReturnKey:
			if (gui.menu.draw) { 
				key=0;
				break;
			}
			if (*gBootArgs == '?') {
				char * argPtr = gBootArgs;

				// Skip the leading "?" character.
				argPtr++;
				getNextArg(&argPtr, booterCommand);
				getNextArg(&argPtr, booterParam);

				/*
				* TODO: this needs to be refactored.
				*/
				if (strcmp( booterCommand, "video" ) == 0) {
					if (bootArgs->Video.v_display != VGA_TEXT_MODE) {
						showInfoBox(getVBEInfoString(), getVBEModeInfoString());
					} else {
						printVBEModeInfo();
					}
				} else if ( strcmp( booterCommand, "memory" ) == 0) {
					if (bootArgs->Video.v_display != VGA_TEXT_MODE ) {
						showInfoBox("Memory Map", getMemoryInfoString());
					} else {
						printMemoryInfo();
					}
				} else if (strcmp(booterCommand, "lspci") == 0) {
					lspci();
				} else if (strcmp(booterCommand, "more") == 0) {
					showTextFile(booterParam);
				} else if (strcmp(booterCommand, "rd") == 0) {
					processRAMDiskCommand(&argPtr, booterParam);
				} else if (strcmp(booterCommand, "norescan") == 0) {
					if (gEnableCDROMRescan) {
						gEnableCDROMRescan = false;
						break;
					}
				} else {
					showHelp();
				}
				key = 0;
				showBootPrompt(nextRow, showPrompt);
				break;
			}
			gBootVolume = menuBVR;
			setRootVolume(menuBVR);
			gBIOSDev = menuBVR->biosdev;
			break;

		case kEscapeKey:
			clearBootArgs();
			break;

		case kF5Key:
			// New behavior:
			// Clear gBootVolume to restart the loop
			// if the user enabled rescanning the optical drive.
			// Otherwise boot the default boot volume.
			if (gEnableCDROMRescan) {
				gBootVolume = NULL;
				clearBootArgs();
			}
			break;

		case kF10Key:
			gScanSingleDrive = false;
			scanDisks(gBIOSDev, &bvCount);
			gBootVolume = NULL;
			clearBootArgs();
			break;

		case kTabKey:
			// New behavior:
			// Switch between text & graphic interfaces
			// Only Permitted if started in graphics interface
			if (useGUI) {
				if (bootArgs->Video.v_display != VGA_TEXT_MODE) {
					setVideoMode(VGA_TEXT_MODE, 0);

					setCursorPosition(0, 0, 0);
					clearScreenRows(0, kScreenLastRow);

					// Display banner and show hardware info.
					printf(bootBanner, (bootInfo->convmem + bootInfo->extmem) / 1024);
					printf(getVBEInfoString());

					clearScreenRows(kMenuTopRow, kMenuTopRow + 2);
					changeCursor(0, kMenuTopRow, kCursorTypeHidden, 0);

					nextRow = kMenuTopRow;
					showPrompt = true;

					if (gDeviceCount) {
						printf("Use \30\31 keys to select the startup volume.");
						showMenu(menuItems, gDeviceCount, selectIndex, kMenuTopRow + 2, kMenuMaxItems);
						nextRow += MIN(gDeviceCount, kMenuMaxItems) + 3;
					}

					showPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot);
					showBootPrompt(nextRow, showPrompt);
					//changeCursor( 0, kMenuTopRow, kCursorTypeUnderline, 0 );
				} else {
					gui.redraw = true;
					setVideoMode(GRAPHICS_MODE, 0);
					updateVRAM();
                    updateGraphicBootPrompt();
				}
			}
			key = 0;
			break;

		default:
			key = 0;
			break;
		}
	} while (0 == key);

done:
	if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
		clearScreenRows(kMenuTopRow, kScreenLastRow);
		changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0);
	}
	shouldboot = false;
	gui.menu.draw = false;
	if (menuItems) {
		free(menuItems);
		menuItems = NULL;
	}
    
    if(shouldAddBootUuid) {
        char tmp[512];
        const char* val;
        int cnt;
        if(getValueForKey("hajobootuuid", &val, &cnt, &bootInfo->chameleonConfig)) {
            strncpy(tmp, val, cnt);
            tmp[cnt] = 0;
            addBootArg(tmp);
        }
    }
    shouldAddBootUuid = true;
	
    return 0;
}
Esempio n. 7
0
File: boot.c Progetto: 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();
    }
}
Esempio n. 8
0
int
getBootOptions(BOOL firstRun)
{
    int     i;
    int     key;
    int     selectIndex = 0;
    int     bvCount;
    int     nextRow;
    int     timeout;
    BVRef   bvr;
    BVRef   bvChain;
    BVRef   menuBVR;
    BOOL    showPrompt, newShowPrompt, isCDROM;
    MenuItem *  menuItems = NULL;

    if ( diskIsCDROM(gBootVolume) )
        isCDROM = TRUE;
    else
        isCDROM = FALSE;

    // Allow user to override default timeout.

    if ( getIntForKey(kTimeoutKey, &timeout) == NO )
    {
        if ( isCDROM )
            timeout = kCDBootTimeout;
        else
            timeout = kBootTimeout;
    }
    if (timeout < 0) gBootMode |= kBootModeQuiet;

    // If the user is holding down a modifier key,
    // enter safe mode.
    if ( ( readKeyboardShiftFlags() & 0x0F ) != 0 ) {
        gBootMode |= kBootModeSafe;
    }

    // If user typed F8, abort quiet mode,
    // and display the menu.
    if (flushKeyboardBuffer()) {
        gBootMode &= ~kBootModeQuiet;
        timeout = 0;
    }

    clearBootArgs();

    setCursorPosition( 0, 0, 0 );
    clearScreenRows( 0, kScreenLastRow );
    if ( ! ( gBootMode & kBootModeQuiet ) ) {
        // Display banner and show hardware info. 
        printf( bootBanner, (bootInfo->convmem + bootInfo->extmem) / 1024 );
        printVBEInfo();
    }

    changeCursor( 0, kMenuTopRow, kCursorTypeUnderline, 0 );

    verbose("Scanning device %x...", gBIOSDev);

    // Get a list of bootable volumes on the device.

    bvChain = scanBootVolumes( gBIOSDev, &bvCount );
    gBootVolume = menuBVR = selectBootVolume( bvChain );

    // When booting from CD, default to hard
    // drive boot when possible. 

    if ( isCDROM )
    {
        const char *val;
        char *prompt;
        int cnt;
        int optionKey;

        if (getValueForKey( kCDROMPromptKey, &val, &cnt )) {
            cnt += 1;
            prompt = malloc(cnt);
            strlcpy(prompt, val, cnt);
        } else {
            prompt = "Press any key to start up from CD-ROM, "
                "or press F8 to enter startup options.";
            cnt = 0;
        }

        if (getIntForKey( kCDROMOptionKey, &optionKey )) {
            // The key specified is a special key.
        } else if (getValueForKey( kCDROMOptionKey, &val, &cnt) && cnt >= 1) {
            optionKey = val[0];
        } else {
            // Default to F8.
            optionKey = 0x4200;
        }

        key = countdown(prompt, kMenuTopRow, timeout);
        if (cnt)
            free(prompt);

        clearScreenRows( kMenuTopRow, kMenuTopRow + 2 );

        if (key == 0) {
            // Boot from hard disk.
            // Scan the original device 0x80.

            BVRef hd_bvr = selectBootVolume(scanBootVolumes(0x80, 0));
            if ( hd_bvr->flags & kBVFlagNativeBoot ) {
                gBootVolume = hd_bvr;
                gBIOSDev = hd_bvr->biosdev;
                initKernBootStruct( gBIOSDev );
                goto done;
            }
        } else  {
            if (optionKey < 0x100)
                key = key & 0x5F;
            if (key != optionKey)
                goto done;
        }
        gBootMode &= ~kBootModeQuiet;
        timeout = 0;
    }

    if ( gBootMode & kBootModeQuiet )
    {
        // No input allowed from user.
        goto done;
    }

    if ( firstRun && ( timeout > 0 ) &&
         ( countdown("Press any key to enter startup options.",
                     kMenuTopRow, timeout) == 0 ) )
    {
        // If the user is holding down a modifier key,
        // enter safe mode.
        if ( ( readKeyboardShiftFlags() & 0x0F ) != 0 ) {
            gBootMode |= kBootModeSafe;
        }
        goto done;
    }

    if ( bvCount )
    {
        // Allocate memory for an array of menu items.

        menuItems = (MenuItem *) malloc( sizeof(MenuItem) * bvCount );
        if ( menuItems == NULL ) goto done;

        // Associate a menu item for each BVRef.

        for ( bvr = bvChain, i = bvCount - 1, selectIndex = 0;
              bvr; bvr = bvr->next, i-- )
        {
            getBootVolumeDescription( bvr, menuItems[i].name, 80, YES );
            menuItems[i].param = (void *) bvr;
            if ( bvr == menuBVR ) selectIndex = i;
        }
    }

    // Clear screen and hide the blinking cursor.

    clearScreenRows( kMenuTopRow, kMenuTopRow + 2 );
    changeCursor( 0, kMenuTopRow, kCursorTypeHidden, 0 );
    nextRow = kMenuTopRow;
    showPrompt = YES;

    // Show the menu.

    if ( bvCount )
    {
        printf("Use \30\31 keys to select the startup volume.");
        showMenu( menuItems, bvCount, selectIndex, kMenuTopRow + 2, kMenuMaxItems );
        nextRow += min( bvCount, kMenuMaxItems ) + 3;
    }

    // Show the boot prompt.

    showPrompt = (bvCount == 0) || (menuBVR->flags & kBVFlagNativeBoot);
    showBootPrompt( nextRow, showPrompt );

    do {
        key = getc();

        updateMenu( key, (void **) &menuBVR );

        newShowPrompt = (bvCount == 0) ||
                        (menuBVR->flags & kBVFlagNativeBoot);

        if ( newShowPrompt != showPrompt )
        {
            showPrompt = newShowPrompt;
            showBootPrompt( nextRow, showPrompt );
        }
        if ( showPrompt ) updateBootArgs( key );

        switch ( key & kASCIIKeyMask )
        {
            case kReturnKey:
                if ( *gBootArgs == '?' )
                {
                    if ( strcmp( gBootArgs, "?video" ) == 0 ) {
                        printVBEModeInfo();
                    } else if ( strcmp( gBootArgs, "?memory" ) == 0 ) {
                        printMemoryInfo();
                    } else {
                        showHelp();
                    }
                    key = 0;
                    showBootPrompt( nextRow, showPrompt );
                    break;
                }
                gBootVolume = menuBVR;
                break;

            case kEscapeKey:
                clearBootArgs();
                break;

            default:
                key = 0;
        }
    }
    while ( 0 == key );

done:
    firstRun = NO;

    clearScreenRows( kMenuTopRow, kScreenLastRow );
    changeCursor( 0, kMenuTopRow, kCursorTypeUnderline, 0 );

    if ( menuItems ) free(menuItems);

    return 0;
}
Esempio n. 9
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;
}
Esempio n. 10
0
void NBI_PreBoot_hook(void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6)
{	
	
	bool dummyVal = 0;
	config_file_t systemVersion;
	
	char valid = false;
	const char *val;
	int len;
	const char* gPrevMacOSBuildVersion;
	
	
	if (!loadConfigFile("System/Library/CoreServices/SystemVersion.plist", &systemVersion))
	{
		valid = true;
	}
	else if (!loadConfigFile("System/Library/CoreServices/ServerVersion.plist", &systemVersion))
	{
		valid = true;
	}
	
	if (valid)
	{
		if  (getValueForKey("ProductBuildVersion", &val, &len, &systemVersion))
		{
			
			if (!loadConfigFile("Extra/SystemVersion.LastPatched.plist", &systemVersion))
			{
				if(getValueForKey("ProductBuildVersion", &gPrevMacOSBuildVersion, &len, &systemVersion))
				{
					if(strlen(val) != strlen(gPrevMacOSBuildVersion) ||
					   strcmp(val, gPrevMacOSBuildVersion) != 0
					   )
					{
						runNetbookInstaller = 1;
					}
					else 
					{
						// Only allow restore from hibernation if the system hasn't changed, probably a bad idea though
						//char* val="/private/var/vm/sleepimage";
						
						// Do this first to be sure that root volume is mounted
						//ret = GetFileInfo(0, val, &flags, &sleeptime);
						
						//printf("System version has not changed\n");
						//runNetbookInstaller = 0;
						
					}
					
				}
			}
		}
	}
	
	
	
	
	
	if (!runNetbookInstaller && getBoolForKey("recovery", &dummyVal, DEFAULT_BOOT_CONFIG) && dummyVal)
	{
		if(dummyVal) runNetbookInstaller = 2;
	}
	
	if(runNetbookInstaller)
	{
		
		replace_system_function("_LoadDrivers", &NBI_LoadDrivers);
		
		if(runNetbookInstaller == 1 )
		{
			if (execute_hook("isRamDiskRegistred", NULL, NULL, NULL, NULL, NULL, NULL) == EFI_SUCCESS)
			{
				replace_function_any("_md0Ramdisk", &NBI_md0Ramdisk);
			} 
			else
			{
				register_hook_callback("md0Ramdisk", NBI_md0Ramdisk_hook);
			}
			
		}
		
		// Force arch=i386 + -v
		safe_set_env(envarchCpuType, CPU_TYPE_I386);
		safe_set_env(envgVerboseMode, true);
	}
}
Esempio n. 11
0
// Notify OS X that a ramdisk has been setup. XNU will attach this to /dev/md0
void md0Ramdisk()
{
	RAMDiskParam ramdiskPtr;
	char filename[512];
	const char* override_filename = 0;
	int fh = -1;
	int len;
	
	if (getValueForKey(kMD0ImageKey, &override_filename, &len, &bootInfo->bootConfig))
	{
		// Use user specified md0 file
		sprintf(filename, "%s", override_filename);
		fh = open(filename, 0);
		
		if (fh < 0)
		{
			sprintf(filename, "rd(0,0)/Extra/Postboot.img");
			fh = open(filename, 0);

			if (fh < 0)
			{
				sprintf(filename, "bt(0,0)/Extra/Postboot.img");	// Check /Extra if not in rd(0,0)
				fh = open(filename, 0);
			}
		}		
	}		

	if (fh >= 0)
	{
		verbose("Enabling ramdisk %s\n", filename);

		ramdiskPtr.size = file_size(fh);
		ramdiskPtr.base = AllocateKernelMemory(ramdiskPtr.size);

		if (ramdiskPtr.size && ramdiskPtr.base)
		{
			// Read new ramdisk image contents in kernel memory.
			if (read(fh, (char*) ramdiskPtr.base, ramdiskPtr.size) == ramdiskPtr.size)
			{
				AllocateMemoryRange("RAMDisk", ramdiskPtr.base, ramdiskPtr.size, kBootDriverTypeInvalid);
				Node* node = DT__FindNode("/chosen/memory-map", false);
				if (node != NULL)
				{
					DT__AddProperty(node, "RAMDisk", sizeof(RAMDiskParam),  (void*)&ramdiskPtr);		
				}
				else
				{
					verbose("Unable to notify Mac OS X of the ramdisk %s.\n", filename);
				}
			}
			else
			{
				verbose("Unable to read md0 image %s.\n", filename);
			}			
		}
		else
		{
			verbose("md0 image %s is empty.\n", filename);
		}

		close(fh);
	}
}
Esempio n. 12
0
File: options.c Progetto: aosm/boot
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;
}
Esempio n. 13
0
//==========================================================================
// The 'main' function for the booter. Called by boot0 when booting
// from a block device, or by the network booter.
//
// arguments:
//   biosdev - Value passed from boot1/NBP to specify the device
//             that the booter was loaded from.
//
// If biosdev is kBIOSDevNetwork, then this function will return if
// booting was unsuccessful. This allows the PXE firmware to try the
// next boot device on its list.
void common_boot(int biosdev)
{
    const char		*val;
    char		*bootFile;
    unsigned long	adler32;
    int			status;
    int			cnt;
    bool		quiet;
    bool		firstRun = true;
    bool		instantMenu;
    bool		rescanPrompt;

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

    // Initialize boot info structure.
    initKernBootStruct();

    // Setup VGA text mode.
    // Not sure if it is safe to call setVideoMode() before the
    // config table has been loaded. Call video_mode() instead.
#if DEBUG
    printf("before video_mode\n");
#endif
    video_mode( 2 );  // 80x25 mono text mode.
#if DEBUG
    printf("after video_mode\n");
#endif

    // First get info for boot volume.
    scanBootVolumes(gBIOSDev, 0);
    bvChain = getBVChainForBIOSDev(gBIOSDev);
    setBootGlobals(bvChain);
    
    // Load boot.plist config file
    status = loadSystemConfig(&bootInfo->bootConfig);

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

    // Get verbosity at early stage to allow a quiet booter
    if (getValueForKey(kKernelFlagsKey, &val, &cnt, &bootInfo->bootConfig)) {
	    if (getValueForBootKey(val, kVerboseModeFlag, &val, &cnt)) {
		    gVerboseMode = true;
	    }
    }

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

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

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

    // Disable rescan option by default
    gEnableCDROMRescan = false;

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

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

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

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

    // Create a separated bvr chain using the specified filters.
    bvChain = newFilteredBVChain(0x80, 0xFF, kBVFlagSystemVolume|kBVFlagForeignBoot, kBVFlagEFISystem, &gDeviceCount);

    gBootVolume = selectBootVolume(bvChain);

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

    useGUI = true;
    // Override useGUI default
    getBoolForKey(kGUIKey, &useGUI, &bootInfo->bootConfig);
    if (useGUI) {
	if (gVerboseMode) {
		printf("Switching to GUI mode in 3 seconds...\n");
		sleep(3);
	}
	initGUI();
        /* XXX AsereBLN handle error */
    }

    setBootGlobals(bvChain);

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

        config_file_t    systemVersion;		// system.plist of booting partition

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

	getBootOptions(firstRun);
        firstRun = false;

        status = processBootOptions();
        // Status==1 means to chainboot
        if ( status ==  1 ) break;
        // Status==-1 means that the config file couldn't be loaded or that gBootVolume is NULL
        if ( status == -1 )
        {
          // gBootVolume == NULL usually means the user hit escape.
          if(gBootVolume == NULL)
          {
            freeFilteredBVChain(bvChain);

            if (gEnableCDROMRescan)
              rescanBIOSDevice(gBIOSDev);
              
            bvChain = newFilteredBVChain(0x80, 0xFF, kBVFlagSystemVolume|kBVFlagForeignBoot, kBVFlagEFISystem, &gDeviceCount);
            setBootGlobals(bvChain);
          }
          continue;
        }
		
        // Other status (e.g. 0) means that we should proceed with boot.
		
		if( bootArgs->Video.v_display == GRAPHICS_MODE )
			drawBackground();
			
        // Found and loaded a config file. Proceed with boot.

		// Turn off any GUI elements
		if( bootArgs->Video.v_display == GRAPHICS_MODE )
		{
			gui.devicelist.draw = false;
			gui.bootprompt.draw = false;
			gui.menu.draw = false;
			gui.infobox.draw = false;
			drawBackground();
			updateVRAM();
		}
		
		// Find out which version mac os we're booting.
		if (!loadConfigFile("System/Library/CoreServices/SystemVersion.plist", &systemVersion)) {
			if (getValueForKey(kProductVersion, &val, &len, &systemVersion)) {	
				// getValueForKey uses const char for val
				// so copy it and trim
				strncpy(gMacOSVersion, val, MIN(len, 4));
				gMacOSVersion[MIN(len, 4)] = '\0';
			}
		}

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

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

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

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

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

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

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

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

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

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

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

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

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

			if(gui.initialised) {
				sleep(1);
				drawBackground();
				gui.devicelist.draw = true;
				gui.redraw = true;
			}
        } else {
            /* Won't return if successful. */
            ret = ExecKernel(binary);
        }
    }
    
    // chainboot
    if (status==1) {
	if (getVideoMode() == GRAPHICS_MODE) {	// if we are already in graphics-mode,
		setVideoMode(VGA_TEXT_MODE, 0);	// switch back to text mode
	}
    }
}
Esempio n. 14
0
    void Scene::initialize( const std::vector<ActorUId>& persistent_actors )
    {
        mSceneManager = EventManager::create("Scene "+mName+" Manager");
        Controller::get()->eventManager()->addListener(fastdelegate::MakeDelegate(this, &Scene::handleInitGUI), InitGUIEvent::TYPE);
        Controller::get()->eventManager()->addListener( fastdelegate::MakeDelegate(this, &Scene::handleSceneUpdate), SceneUpdateEvent::TYPE );
        Controller::get()->eventManager()->addListener( fastdelegate::MakeDelegate(this, &Scene::handleReturnActorCreate), ReturnActorCreatedEvent::TYPE );
        Controller::get()->eventManager()->addListener( fastdelegate::MakeDelegate(this, &Scene::handleScenePreDraw), ScenePreDrawEvent::TYPE );
        Controller::get()->eventManager()->addListener( fastdelegate::MakeDelegate(this, &Scene::handleSceneDraw), SceneDrawEvent::TYPE );
        Controller::get()->eventManager()->addListener( fastdelegate::MakeDelegate(this, &Scene::handleShutDown), ShutDownEvent::TYPE );
        
        if( !persistent_actors.empty() ){
            for(auto &id : persistent_actors)
            {
                auto actor_weak = ActorManager::get()->retreiveUnique(id);
                mActors.insert( std::make_pair(id, actor_weak) );
            }
        }
        
        auto init = ConfigManager::get()->retreiveActorsForScene( mName );
        
        ///call to inherited initialize for sub classes to pulll custom shit out of the config
        initialize( ConfigManager::get()->retreiveScene(mName) );
        
        try {
            
            //TODO: the problem with persistent actors is how to manage state across scenes, how to identify actors of the same type across scenes that are persistent, one solution is destroy all and reload referencing a serialized state file that is written out and read back in or something
            //for now, just sending across actors marked 'persistent' and not including them in the config for the next scene, the state has to be handled at runtime then
            
            auto & actors = init.getChildren();
            
            auto it = actors.begin();
            auto end = actors.end();
            for(;it!=end;++it){
                auto actor_name = it->getValueForKey("name");
                CI_LOG_V("found actor: "+actor_name);

                auto onInit = it->getValueForKey<bool>( "create_on_scene_init" );
                auto persistent = it->getValueForKey<bool>( "persistent" );
                
                if( persistent ){
                    //make sure its not already in there
                   if( !ec::ActorManager::get()->actorExists( ec::getHash(actor_name) ) ){
                       if( onInit ){
                           //make sure it shuld be created on scene init
                           CI_LOG_V("creating actor: "+actor_name);
                           Controller::get()->eventManager()->triggerEvent( CreateActorEvent::create( mName, actor_name) );
                       }
                    }
                }else if (onInit){
                    //make sure it shuld be created on scene init
                    CI_LOG_V("creating actor: "+actor_name);
                    Controller::get()->eventManager()->triggerEvent( CreateActorEvent::create( mName, actor_name) );

                }

                
            }
            
        } catch (const ci::JsonTree::ExcChildNotFound &e) {
            CI_LOG_E("actors not found in init");
        }
        
      
        ///POST INITIALIZE ALL ACTORS
        auto actor = mActors.begin();
        auto end = mActors.end();
        
        while( actor != end )
        {
            if(auto a = (*actor).second.lock()){
                a->postInit();
                ++actor;
            }else{
                CI_LOG_E("Actor is missing");
                ec::Controller::get()->eventManager()->triggerEvent(DestoryActorEvent::create((*actor).first));
                actor = mActors.erase(actor);
            }
        }
        
        postInit();
        
        ///run setup events;
        manager()->update();
        
    }
Esempio n. 15
0
bool setup_gma_devprop(pci_dt_t *gma_dev)
{
	char				*devicepath = NULL;
	volatile uint8_t		*regs;
	uint32_t			bar[7];
	char				*model = NULL;
	uint8_t BuiltIn =		0x00;
	uint16_t			vendor_id = gma_dev->vendor_id;
	uint16_t			device_id = gma_dev->device_id;
	uint8_t ClassFix[4] =           { 0x00, 0x00, 0x03, 0x00 };
	int				n_igs = 0;
	int				len;
	const char			*value;
	devicepath = get_pci_dev_path(gma_dev);

	bar[0] = pci_config_read32(gma_dev->dev.addr, 0x10);
	regs = (uint8_t *) (bar[0] & ~0x0f);

	model = get_gma_controller_name(device_id, vendor_id);

	verbose("---------------------------------------------\n");
   	verbose("------------ INTEL DEVICE INFO --------------\n");
	verbose("---------------------------------------------\n");
	verbose("Class code: [%04x]\n%s [%04x:%04x] (rev %02x)\nSubsystem: [%04x:%04x] :: %s\n",
			gma_dev->class_id, model, gma_dev->vendor_id, gma_dev->device_id, gma_dev->revision_id, gma_dev->subsys_id.subsys.vendor_id, gma_dev->subsys_id.subsys.device_id, devicepath);

	if (!string) {
		string = devprop_create_string();
	}

	struct DevPropDevice *device = devprop_add_device(string, devicepath);
	if (!device) {
		printf("Failed initializing dev-prop string dev-entry.\n");
		pause();
		return false;
	}

	devprop_add_value(device, "model", (uint8_t*)model, (strlen(model) + 1));
	devprop_add_value(device, "device_type", (uint8_t*)"display", 8);


	switch ((device_id << 16) | vendor_id)
	{
        case GMA_IRONLAKE_D_G: // 0042
        case GMA_IRONLAKE_M_G: // 0046
            devprop_add_value(device, "built-in", &BuiltIn, 1);
            devprop_add_value(device, "class-code", ClassFix, 4);
            devprop_add_value(device, "hda-gfx",			(uint8_t *)"onboard-1", 10);
            devprop_add_value(device, "AAPL,os-info",			HDx000_os_info, 20);
            break;
            /* 27A2, 27AE, 27A6, A001, A011, A012, */
        case GMA_I945_GM: // Mobile GMA950 Mobile GMA3150
        case GMA_I945_GME:
        //case GMA_945GM:
        case GMA_PINEVIEW_G:
        case GMA_PINEVIEW_M:
        case GMA_GMA3150_M:
            devprop_add_value(device, "AAPL,HasPanel", reg_TRUE, 4);
            devprop_add_value(device, "built-in", &BuiltIn, 1);
            devprop_add_value(device, "class-code", ClassFix, 4);
            break;

            /* 2772 ,2776, A002 */
        case GMA_I945_G: // Desktop GMA950 Desktop GMA3150
        //case GMA_82945G:
        case GMA_GMA3150_D:
            BuiltIn = 0x01;
            devprop_add_value(device, "built-in", &BuiltIn, 1);
            devprop_add_value(device, "class-code", ClassFix, 4);
            break;

            /* 2A02, 2A12, 2A13, 2A42, 2A43 */
        case GMA_I965_GM: // GMAX3100
        case GMA_I965_GME:
        //case 0x80862A13:
        case GMA_GM45_GM:
        //case GMA_GM45_GM2:
            devprop_add_value(device, "AAPL,HasPanel",                  GMAX3100_vals[0], 4);
            devprop_add_value(device, "AAPL,SelfRefreshSupported",	GMAX3100_vals[1], 4);
            devprop_add_value(device, "AAPL,aux-power-connected",	GMAX3100_vals[2], 4);
            devprop_add_value(device, "AAPL,backlight-control",         GMAX3100_vals[3], 4);
            devprop_add_value(device, "AAPL00,blackscreen-preferences",	GMAX3100_vals[4], 4);
            devprop_add_value(device, "AAPL01,BacklightIntensity",	GMAX3100_vals[5], 4);
            devprop_add_value(device, "AAPL01,blackscreen-preferences",	GMAX3100_vals[6], 4);
            devprop_add_value(device, "AAPL01,DataJustify",             GMAX3100_vals[7], 4);
            devprop_add_value(device, "AAPL01,Depth",                   GMAX3100_vals[8], 4);
            devprop_add_value(device, "AAPL01,Dither",                  GMAX3100_vals[9], 4);
            devprop_add_value(device, "AAPL01,DualLink",                GMAX3100_vals[10], 4);
            devprop_add_value(device, "AAPL01,Height",                  GMAX3100_vals[11], 4);
            devprop_add_value(device, "AAPL01,Interlace",               GMAX3100_vals[12], 4);
            devprop_add_value(device, "AAPL01,Inverter",                GMAX3100_vals[13], 4);
            devprop_add_value(device, "AAPL01,InverterCurrent",         GMAX3100_vals[14], 4);
            devprop_add_value(device, "AAPL01,InverterCurrency",	GMAX3100_vals[15], 4);
            devprop_add_value(device, "AAPL01,LinkFormat",              GMAX3100_vals[16], 4);
            devprop_add_value(device, "AAPL01,LinkType",                GMAX3100_vals[17], 4);
            devprop_add_value(device, "AAPL01,Pipe",                    GMAX3100_vals[18], 4);
            devprop_add_value(device, "AAPL01,PixelFormat",             GMAX3100_vals[19], 4);
            devprop_add_value(device, "AAPL01,Refresh",                 GMAX3100_vals[20], 4);
            devprop_add_value(device, "AAPL01,Stretch",                 GMAX3100_vals[21], 4);
            //devprop_add_value(device, "AAPL01,InverterFrequency",	GMAX3100_vals[22], 4);
            devprop_add_value(device, "class-code",                     ClassFix, 4);
            break;

            /* 0106 */
        case GMA_SANDYBRIDGE_M_GT1: // HD Graphics 2000 Mobile
            devprop_add_value(device, "class-code", ClassFix, 4);
            devprop_add_value(device, "hda-gfx",			(uint8_t *)"onboard-1", 10);
            devprop_add_value(device, "AAPL00,PixelFormat",		HD2000_vals[0], 4);
            devprop_add_value(device, "AAPL00,T1",			HD2000_vals[1], 4);
            devprop_add_value(device, "AAPL00,T2",			HD2000_vals[2], 4);
            devprop_add_value(device, "AAPL00,T3",			HD2000_vals[3], 4);
            devprop_add_value(device, "AAPL00,T4",			HD2000_vals[4], 4);
            devprop_add_value(device, "AAPL00,T5",			HD2000_vals[5], 4);
            devprop_add_value(device, "AAPL00,T6",			HD2000_vals[6], 4);
            devprop_add_value(device, "AAPL00,T7",			HD2000_vals[7], 4);
            devprop_add_value(device, "AAPL00,LinkType",		HD2000_vals[8], 4);
            devprop_add_value(device, "AAPL00,LinkFormat",		HD2000_vals[9], 4);
            devprop_add_value(device, "AAPL00,DualLink",		HD2000_vals[10], 4);
            devprop_add_value(device, "AAPL00,Dither",			HD2000_vals[11], 4);
            devprop_add_value(device, "AAPL00,DataJustify",		HD3000_vals[12], 4);
            devprop_add_value(device, "graphic-options",		HD2000_vals[13], 4);
            devprop_add_value(device, "AAPL,tbl-info",			HD2000_tbl_info, 18);
            devprop_add_value(device, "AAPL,os-info",			HD2000_os_info, 20);
            break;

            /* 0116, 0126 */
        case GMA_SANDYBRIDGE_M_GT2: // HD Graphics 3000 Mobile
        case GMA_SANDYBRIDGE_M_GT2_PLUS:
            devprop_add_value(device, "class-code",			ClassFix, 4);
            devprop_add_value(device, "hda-gfx",			(uint8_t *)"onboard-1", 10);
            devprop_add_value(device, "AAPL00,PixelFormat",		HD3000_vals[0], 4);
            devprop_add_value(device, "AAPL00,T1",			HD3000_vals[1], 4);
            devprop_add_value(device, "AAPL00,T2",			HD3000_vals[2], 4);
            devprop_add_value(device, "AAPL00,T3",			HD3000_vals[3], 4);
            devprop_add_value(device, "AAPL00,T4",			HD3000_vals[4], 4);
            devprop_add_value(device, "AAPL00,T5",			HD3000_vals[5], 4);
            devprop_add_value(device, "AAPL00,T6",			HD3000_vals[6], 4);
            devprop_add_value(device, "AAPL00,T7",			HD3000_vals[7], 4);
            devprop_add_value(device, "AAPL00,LinkType",		HD3000_vals[8], 4);
            devprop_add_value(device, "AAPL00,LinkFormat",		HD3000_vals[9], 4);
            devprop_add_value(device, "AAPL00,DualLink",		HD3000_vals[10], 4);
            devprop_add_value(device, "AAPL00,Dither",			HD3000_vals[11], 4);
            devprop_add_value(device, "AAPL00,DataJustify",		HD3000_vals[12], 4);
            devprop_add_value(device, "graphic-options",		HD3000_vals[13], 4);
            devprop_add_value(device, "AAPL,tbl-info",			HD3000_tbl_info, 18);
            devprop_add_value(device, "AAPL,os-info",			HD3000_os_info, 20);
            devprop_add_value(device, "AAPL,snb-platform-id",		HD3000_vals[16], 4);// previusly commented
            break;

        /* 0102 */
        /* HD Graphics 2000 */
        case GMA_SANDYBRIDGE_GT1: // 0102
            device_id = 0x00000102;					// Inject a valid mobile GPU device id instead of patching kexts
            devprop_add_value(device, "built-in",			&BuiltIn, 1);
            devprop_add_value(device, "class-code",			ClassFix, 4);
            devprop_add_value(device, "device-id",			(uint8_t*)&device_id, sizeof(device_id));
            devprop_add_value(device, "hda-gfx",			(uint8_t *)"onboard-1", 10);
            devprop_add_value(device, "AAPL,tbl-info",			HD2000_tbl_info, 18);
            devprop_add_value(device, "AAPL,os-info",			HD2000_os_info, 20);
            break;

        /* Sandy Bridge */
        /* HD Graphics 3000 */
        case GMA_SANDYBRIDGE_GT2: // 0112
        case GMA_SANDYBRIDGE_GT2_PLUS: // 0122
            devprop_add_value(device, "built-in",			&BuiltIn, 1);
            devprop_add_value(device, "class-code",			ClassFix, 4);
            device_id = 0x00000126;					// Inject a valid mobile GPU device id instead of patching kexts
            devprop_add_value(device, "device-id",			(uint8_t*)&device_id, sizeof(device_id));
            devprop_add_value(device, "hda-gfx",			(uint8_t *)"onboard-1", 10);
            devprop_add_value(device, "AAPL,tbl-info",			HD3000_tbl_info, 18);
            devprop_add_value(device, "AAPL,os-info",			HD3000_os_info, 20);
            break;

        /* Ivy Bridge */
        /* HD Graphics 4000, HD Graphics 4000 Mobile, HD Graphics P4000, HD Graphics 2500 HD, Graphics 2500 Mobile */
        case GMA_IVYBRIDGE_D_GT1: // 0152
        case GMA_IVYBRIDGE_M_GT1: // 0156
        case GMA_IVYBRIDGE_S_GT1: // 015A
        case GMA_IVYBRIDGE_S_GT3: // 015e
        case GMA_IVYBRIDGE_D_GT2: // 0162
        case GMA_IVYBRIDGE_M_GT2: // 0166
        case GMA_IVYBRIDGE_S_GT2: // 016A
        case GMA_IVYBRIDGE_S_GT4: // 0172
        case GMA_IVYBRIDGE_S_GT5: // 0176

		if (getValueForKey(kAAPLCustomIG, &value, &len, &bootInfo->chameleonConfig) && len == AAPL_LEN_IVY * 2)
		{
			uint8_t new_aapl0[AAPL_LEN_IVY];

			if (hex2bin(value, new_aapl0, AAPL_LEN_IVY) == 0)
			{
				memcpy(default_aapl_ivy, new_aapl0, AAPL_LEN_IVY);

				verbose("Using user supplied AAPL,ig-platform-id\n");
				verbose("AAPL,ig-platform-id: %02x%02x%02x%02x\n",
				default_aapl_ivy[0], default_aapl_ivy[1], default_aapl_ivy[2], default_aapl_ivy[3]);
			}
			devprop_add_value(device, "AAPL,ig-platform-id", default_aapl_ivy, AAPL_LEN_IVY);
		}
		else if (getIntForKey(kIntelCapriFB, &n_igs, &bootInfo->chameleonConfig))
		{
			if ((n_igs >= 0) || (n_igs <= 11))
			{
				verbose("AAPL,ig-platform-id was set in org.chameleon.Boot.plist with value %d\n", n_igs);
				devprop_add_value(device, "AAPL,ig-platform-id", ivy_bridge_ig_vals[n_igs], 4);
			}
			else
			{
				verbose("AAPL,ig-platform-id was set in org.chameleon.Boot.plist with bad value please choose a number between 0 and 11.\n");
			}
		}
		else
		{
			uint32_t ig_platform_id;
			uint32_t ram = (((getVBEVideoRam() + 512) / 1024) + 512) / 1024;
			switch (ram)
			{
				case 96:
					ig_platform_id = 0x01660000; // 96mb Mobile
					break;

				case 64:
					ig_platform_id = 0x01660009; // 64mb Mobile
					break;

				case 32:
					ig_platform_id = 0x01620005; // 32mb Desktop
					break;

				default:
					printf("Please specify 96, 64, or 32MB RAM for the HD4000 in the bios.\n"
					"The selected %dMB RAM configuration is not supported for the  HD4000.\n", ram);
					pause();
					return false;	// Exit early before the AAPL,ig-platform-id property is set.
					break;
			}
			devprop_add_value(device, "AAPL,ig-platform-id", (uint8_t *)&ig_platform_id, 4);
		}

		devprop_add_value(device, "AAPL00,DualLink",    HD4000_vals[10], 4);
		devprop_add_value(device, "built-in", &BuiltIn, 1);
		devprop_add_value(device, "class-code", ClassFix, 4);
		devprop_add_value(device, "hda-gfx", (uint8_t *)"onboard-1", 10);
		break;

        /* Haswell */
        /* HD Graphics 5000, HD Graphics 5000 Mobile, HD Graphics P5000, HD Graphics 4600, HD Graphics 4600 Mobile */
        //case 0x80860090:
        //case 0x80860091:
        //case 0x80860092:
        case GMA_HASWELL_D_GT1: // 0402
        case GMA_HASWELL_M_GT1: // 0406
        case GMA_HASWELL_S_GT1: // 040a
        case GMA_HASWELL_D_GT2: // 0412
        case GMA_HASWELL_M_GT2: // 0416
        case GMA_HASWELL_S_GT2: // 041a
        case GMA_HASWELL_E_GT1: // 040e
        case GMA_HASWELL_E_GT2: // 041e
        case GMA_HASWELL_E_GT3: // 042e
        case GMA_HASWELL_D_GT3: // 0422
        case GMA_HASWELL_M_GT3: // 0426
        case GMA_HASWELL_S_GT3: // 042a
        case GMA_HASWELL_ULT_M_GT1: // 0a06
        case GMA_HASWELL_ULT_E_GT1: // 0a0e
        case GMA_HASWELL_ULT_M_GT2: // 0a16
        case GMA_HASWELL_ULT_E_GT2: // 0a1e
        case GMA_HASWELL_ULT_D_GT3: // 0a22
        case GMA_HASWELL_ULT_M_GT3: // 0a26
        case GMA_HASWELL_ULT_S_GT3: // 0a2a
        case GMA_HASWELL_ULT_E_GT3: // 0a2e
        case GMA_HASWELL_SDV_D_GT1_IG: // 0c02
        case GMA_HASWELL_SDV_M_GT1_IG: // 0c06
        case GMA_HASWELL_SDV_D_GT2_IG: // 0c12
        case GMA_HASWELL_SDV_M_GT2_IG: // 0c16
        case GMA_HASWELL_SDV_D_GT2_PLUS_IG: // 0c22
        case GMA_HASWELL_SDV_M_GT2_PLUS_IG: // 0c26
        case GMA_HASWELL_CRW_D_GT1: // 0d02
        case GMA_HASWELL_CRW_D_GT2: // 0d12
        case GMA_HASWELL_CRW_D_GT3: // 0d22
        case GMA_HASWELL_CRW_M_GT1: // 0d06
        case GMA_HASWELL_CRW_M_GT2: // 0d16
        case GMA_HASWELL_CRW_M_GT3: // 0d26
        case GMA_HASWELL_CRW_S_GT1: // 0d0a
        case GMA_HASWELL_CRW_S_GT2: // 0d1a
        case GMA_HASWELL_CRW_S_GT3: // 0d2a
        case GMA_HASWELL_CRW_B_GT1: // 0d0b
        case GMA_HASWELL_CRW_B_GT2: // 0d1b
        case GMA_HASWELL_CRW_B_GT3: // 0d2b
        case GMA_HASWELL_CRW_E_GT1: // 0d0e
        case GMA_HASWELL_CRW_E_GT2: // 0d1e
        case GMA_HASWELL_CRW_E_GT3: // 0d2e
        case GMA_HASWELL_CRW_M_GT2_PLUS_IG: // 0d36

            if (getValueForKey(kAAPLCustomIG, &value, &len, &bootInfo->chameleonConfig) && len == AAPL_LEN_HSW * 2)
            {
                uint8_t new_aapl0[AAPL_LEN_HSW];
                
                if (hex2bin(value, new_aapl0, AAPL_LEN_HSW) == 0)
                {
                    memcpy(default_aapl_haswell, new_aapl0, AAPL_LEN_HSW);
                    
                    verbose("Using user supplied AAPL,ig-platform-id\n");
                    verbose("AAPL,ig-platform-id: %02x%02x%02x%02x\n",
                            default_aapl_haswell[0], default_aapl_haswell[1], default_aapl_haswell[2], default_aapl_haswell[3]);
                }
                devprop_add_value(device, "AAPL,ig-platform-id", default_aapl_haswell, AAPL_LEN_HSW);
            }
            else if (getIntForKey(kIntelAzulFB, &n_igs, &bootInfo->chameleonConfig))
            {
                if ((n_igs >= 0) || (n_igs <= 15))
                {
                    verbose("AAPL,ig-platform-id was set in org.chameleon.Boot.plist with value %d\n", n_igs);
                    devprop_add_value(device, "AAPL,ig-platform-id", haswell_ig_vals[n_igs], 4);
                }
                else
                {
                    verbose("AAPL,ig-platform-id was set in org.chameleon.Boot.plist with bad value please choose a number between 0 and 15.\n");
                }
            }
            else
            {
		uint32_t ig_platform_id = 0x0000260c; // set the default platform ig
		devprop_add_value(device, "AAPL,ig-platform-id", (uint8_t *)&ig_platform_id, 4);
            }

            devprop_add_value(device, "AAPL00,DualLink",    HD4000_vals[10], 4);
            devprop_add_value(device, "built-in", &BuiltIn, 1);
            devprop_add_value(device, "class-code", ClassFix, 4);
            devprop_add_value(device, "hda-gfx", (uint8_t *)"onboard-1", 10);
            break;

        default:
            break;
	}

	stringdata = malloc(sizeof(uint8_t) * string->length);
	if (!stringdata)
	{
		printf("No stringdata.\n");
		pause();
		return false;
	}

	verbose("---------------------------------------------\n");
	memcpy(stringdata, (uint8_t*)devprop_generate_string(string), string->length);
	stringlength = string->length;

	return true;
}
Esempio n. 16
0
//==========================================================================
// The 'main' function for the booter. Called by boot0 when booting
// from a block device, or by the network booter.
//
// arguments:
//	 biosdev - Value passed from boot1/NBP to specify the device
//			   that the booter was loaded from.
//
// If biosdev is kBIOSDevNetwork, then this function will return if
// booting was unsuccessful. This allows the PXE firmware to try the
// next boot device on its list.
void common_boot(int biosdev)
{
	bool	 		quiet;
	bool	 		firstRun = true;
	bool	 		instantMenu;
	bool	 		rescanPrompt;
	char	 		*bootFile;
	int				status;
	unsigned int	allowBVFlags = kBVFlagSystemVolume | kBVFlagForeignBoot;
	unsigned int	denyBVFlags = kBVFlagEFISystem;
	unsigned long	adler32;
	
	// Set reminder to unload the PXE base code. Neglect to unload
	// the base code will result in a hang or kernel panic.
	gUnloadPXEOnExit = true;
	
	// Record the device that the booter was loaded from.
	gBIOSDev = biosdev & kBIOSDevMask;
	
	// Initialize boot info structure.
	initKernBootStruct();
	
	initBooterLog();
	
	// Setup VGA text mode.
	// Not sure if it is safe to call setVideoMode() before the
	// config table has been loaded. Call video_mode() instead.
#if DEBUG
	printf("before video_mode\n");
#endif
	video_mode( 2 );  // 80x25 mono text mode.
#if DEBUG
	printf("after video_mode\n");
#endif
	
	// Scan and record the system's hardware information.
	scan_platform();
	
	// First get info for boot volume.
	scanBootVolumes(gBIOSDev, 0);
	bvChain = getBVChainForBIOSDev(gBIOSDev);
	setBootGlobals(bvChain);
	
	// Load boot.plist config file
	status = loadChameleonConfig(&bootInfo->chameleonConfig);
	
	if (getBoolForKey(kQuietBootKey, &quiet, &bootInfo->chameleonConfig) && quiet) {
		gBootMode |= kBootModeQuiet;
	}
	
	// Override firstRun to get to the boot menu instantly by setting "Instant Menu"=y in system config
	if (getBoolForKey(kInstantMenuKey, &instantMenu, &bootInfo->chameleonConfig) && instantMenu) {
		firstRun = false;
	}
	
	// Loading preboot ramdisk if exists.
	loadPrebootRAMDisk();
	
	// Disable rescan option by default
	gEnableCDROMRescan = false;
	
	// Enable it with Rescan=y in system config
	if (getBoolForKey(kRescanKey, &gEnableCDROMRescan, &bootInfo->chameleonConfig)
		&& gEnableCDROMRescan) {
		gEnableCDROMRescan = true;
	}
	
	// Ask the user for Rescan option by setting "Rescan Prompt"=y in system config.
	rescanPrompt = false;
	if (getBoolForKey(kRescanPromptKey, &rescanPrompt , &bootInfo->chameleonConfig)
		&& rescanPrompt && biosDevIsCDROM(gBIOSDev))
	{
		gEnableCDROMRescan = promptForRescanOption();
	}
	
	// Enable touching a single BIOS device only if "Scan Single Drive"=y is set in system config.
	if (getBoolForKey(kScanSingleDriveKey, &gScanSingleDrive, &bootInfo->chameleonConfig)
		&& gScanSingleDrive) {
		gScanSingleDrive = true;
	}
	
	// Create a list of partitions on device(s).
	if (gScanSingleDrive) {
		scanBootVolumes(gBIOSDev, &bvCount);
	} else {
		scanDisks(gBIOSDev, &bvCount);
	}
	
	// Create a separated bvr chain using the specified filters.
	bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount);
	
	gBootVolume = selectBootVolume(bvChain);
	
	// Intialize module system 
	init_module_system();
		
#if DEBUG
	printf(" Default: %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n",
			 gBootVolume, gBootVolume->biosdev, gBootVolume->part_no, gBootVolume->flags);
	printf(" bt(0,0): %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n",
			 gBIOSBootVolume, gBIOSBootVolume->biosdev, gBIOSBootVolume->part_no, gBIOSBootVolume->flags);
	getchar();
#endif
	
	useGUI = true;
	// Override useGUI default
	getBoolForKey(kGUIKey, &useGUI, &bootInfo->chameleonConfig);
	if (useGUI && initGUI())
	{
		// initGUI() returned with an error, disabling GUI.
		useGUI = false;
	}
	
	setBootGlobals(bvChain);
	
	// Parse args, load and start kernel.
	while (1)
	{
		bool		tryresume, tryresumedefault, forceresume;
		bool		usecache = false;//true;
		const char	*val;
		int			len, trycache, ret = -1;
		long		flags, cachetime, kerneltime, exttime, sleeptime, time;
		void		*binary = (void *)kLoadAddr;
		
		// additional variable for testing alternate kernel image locations on boot helper partitions.
		char		bootFileSpec[512];
		
		// Initialize globals.
		sysConfigValid = false;
		gErrors		   = false;
		
		status = getBootOptions(firstRun);
		firstRun = false;
		if (status == -1) continue;
		 
		status = processBootOptions();
		// Status == 1 means to chainboot
		if ( status ==	1 ) break;
		// Status == -1 means that the config file couldn't be loaded or that gBootVolume is NULL
		if ( status == -1 )
		{
			// gBootVolume == NULL usually means the user hit escape.
			if (gBootVolume == NULL)
			{
				freeFilteredBVChain(bvChain);
				
				if (gEnableCDROMRescan)
					rescanBIOSDevice(gBIOSDev);
				
				bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount);
				setBootGlobals(bvChain);
				setupDeviceList(&bootInfo->themeConfig);
			}
			continue;
		}
		
		// Other status (e.g. 0) means that we should proceed with boot.
		
		// Turn off any GUI elements
		if ( bootArgs->Video.v_display == GRAPHICS_MODE )
		{
			gui.devicelist.draw = false;
			gui.bootprompt.draw = false;
			gui.menu.draw = false;
			gui.infobox.draw = false;
			gui.logo.draw = false;
			drawBackground();
			updateVRAM();
		}
		
		// Find out which version mac os we're booting.
		getOSVersion();
		
		if (platformCPUFeature(CPU_FEATURE_EM64T)) {
			archCpuType = CPU_TYPE_X86_64;
		} else {
			archCpuType = CPU_TYPE_I386;
		}
		
		if (getValueForKey(karch, &val, &len, &bootInfo->chameleonConfig)) {
			if (strncmp(val, "i386", 4) == 0) {
				archCpuType = CPU_TYPE_I386;
			}
		}
		
		if (getValueForKey(kKernelArchKey, &val, &len, &bootInfo->chameleonConfig)) {
			if (strncmp(val, "i386", 4) == 0) {
				archCpuType = CPU_TYPE_I386;
			}
		}
		
		// Notify modules that we are attempting to boot
		execute_hook("PreBoot", NULL, NULL, NULL, NULL);
		
		if (!getBoolForKey (kWake, &tryresume, &bootInfo->chameleonConfig)) {
			tryresume = true;
			tryresumedefault = true;
		} else {
			tryresumedefault = false;
		}
		
		if (!getBoolForKey (kForceWake, &forceresume, &bootInfo->chameleonConfig)) {
			forceresume = false;
		}
		
		if (forceresume) {
			tryresume = true;
			tryresumedefault = false;
		}
		
		while (tryresume) {
			const char *tmp;
			BVRef bvr;
			if (!getValueForKey(kWakeImage, &val, &len, &bootInfo->chameleonConfig))
				val = "/private/var/vm/sleepimage";
			
			// Do this first to be sure that root volume is mounted
			ret = GetFileInfo(0, val, &flags, &sleeptime);
			
			if ((bvr = getBootVolumeRef(val, &tmp)) == NULL)
				break;
			
			// Can't check if it was hibernation Wake=y is required
			if (bvr->modTime == 0 && tryresumedefault)
				break;
			
			if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat))
				break;
			
			if (!forceresume && ((sleeptime+3)<bvr->modTime)) {
#if DEBUG	
				printf ("Hibernate image is too old by %d seconds. Use ForceWake=y to override\n",
						bvr->modTime-sleeptime);
#endif				  
				break;
			}
			
			HibernateBoot((char *)val);
			break;
		}
		
		getBoolForKey(kUseKernelCache, &usecache, &bootInfo->chameleonConfig);
		if (usecache) {
			if( getValueForKey(kKernelCacheKey, &val, &len, &bootInfo->chameleonConfig) || getValueForKey(kKernelCacheKey, &val, &len, &bootInfo->bootConfig) ) {
				if (val[0] == '\\')
				{
					len--;
					val++;
				}
				strlcpy(gBootKernelCacheFile, val, len + 1);
                verbose("Using kernel cache: \"%s\" \n", gBootKernelCacheFile);
                //sleep(5);
			}
			else {
				// Lion and Mountain Lion prelink kernel cache file␊
				if ((checkOSVersion("10.7")) || (checkOSVersion("10.8"))) {
					sprintf(gBootKernelCacheFile, "%skernelcache", kDefaultCachePathSnow);
				}
				// Snow Leopard
				else if (checkOSVersion("10.6")) {
					sprintf(gBootKernelCacheFile, "kernelcache_%s", (archCpuType == CPU_TYPE_I386)
							? "i386" : "x86_64");
					int lnam = sizeof(gBootKernelCacheFile) + 9; //with adler32
					
					char* name;
					long prev_time = 0;
					
					struct dirstuff* cacheDir = opendir(kDefaultCachePathSnow);
					
					while(readdir(cacheDir, (const char**)&name, &flags, &time) >= 0)
					{
						if (((flags & kFileTypeMask) != kFileTypeDirectory) && time > prev_time
							&& strstr(name, gBootKernelCacheFile) && (name[lnam] != '.'))
						{
							sprintf(gBootKernelCacheFile, "%s%s", kDefaultCachePathSnow, name);
							prev_time = time;
						}
					}
				}
				else {
					// Reset cache name.
					bzero(gCacheNameAdler + 64, sizeof(gCacheNameAdler) - 64);
					
					sprintf(gCacheNameAdler + 64, "%s,%s", gRootDevice, bootInfo->bootFile);
					
					adler32 = Adler32((unsigned char *)gCacheNameAdler, sizeof(gCacheNameAdler));
					
					sprintf(gBootKernelCacheFile, "%s.%08lX", kDefaultCachePathLeo, adler32);
				}
			}
		}
		
		// Check for cache file.
		trycache = (usecache && 
					((gBootMode & kBootModeSafe) == 0) &&
					!gOverrideKernel &&
					(gBootFileType == kBlockDeviceType) &&
					(gMKextName[0] == '\0') &&
					(gBootKernelCacheFile[0] != '\0'));
        
        verbose("trycache: %d\n", trycache);
		
		verbose("Loading Darwin %s\n", gMacOSVersion);
		
		if (trycache) do {
            verbose("bootInfo->bootFile: \"%s\" \n", bootInfo->bootFile);
			ret = GetFileInfo(NULL, bootInfo->bootFile, &flags, &kerneltime);
			if (ret != 0) kerneltime = 0;
			else if ((flags & kFileTypeMask) != kFileTypeFlat) {
				trycache = 0;
                verbose("trycache0 : 1\n");
				break;
			}
			
			ret = GetFileInfo(NULL, gBootKernelCacheFile, &flags, &cachetime);
			if ((ret != 0)) {
				trycache = 0;
                verbose("trycache0 : 2.1 \"%s\" \n", gBootKernelCacheFile);
				break;
			}
			else if ( ((flags & kFileTypeMask) != kFileTypeFlat) ) {
				trycache = 0;
                verbose("trycache0 : 2.2\n");
				break;
			}
			else if ( (cachetime < kerneltime) ) {
				trycache = 0;
                verbose("trycache0 : 2.3\n");
				break;
			}
			
			ret = GetFileInfo("/System/Library/", "Extensions", &flags, &exttime);
			if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)
				&& (cachetime < exttime)) {
				trycache = 0;
                verbose("trycache0 : 3\n");
				break;
			}
			
			if (ret == 0 && kerneltime > exttime) {
				exttime = kerneltime;
			}
			
			if (ret == 0 && cachetime < (exttime + 1)) {
				trycache = 0;
                verbose("trycache0 : 4\n");
				break;
			}
		} while (0);

        // sleep(5);

		do {
			if (trycache) {
				bootFile = gBootKernelCacheFile;
				
				verbose("Loading kernel cache %s\n", bootFile);
				
				if ((checkOSVersion("10.7")) || (checkOSVersion("10.8"))) {
					ret = LoadThinFatFile(bootFile, &binary);
				}
				else {
					ret = LoadFile(bootFile);
					binary = (void *)kLoadAddr;
				}
				
				if (ret >= 0)
					break;
				
				verbose("Kernel cache did not load %s\n ", bootFile);
			}
			
			if ((checkOSVersion("10.7")) || (checkOSVersion("10.8"))) {
				bootFile = gBootKernelCacheFile;
			}
			else {
				sprintf(bootFile, "\%s", bootInfo->bootFile);
			}
			
			// Try to load kernel image from alternate locations on boot helper partitions.
			sprintf(bootFileSpec, "com.apple.boot.P%s", bootFile);
			ret = GetFileInfo(NULL, bootFileSpec, &flags, &time); 
			if (ret == -1)
			{
				sprintf(bootFileSpec, "com.apple.boot.R%s", bootFile);
				ret = GetFileInfo(NULL, bootFileSpec, &flags, &time); 
				if (ret == -1)
				{
					sprintf(bootFileSpec, "com.apple.boot.S%s", bootFile);
					ret = GetFileInfo(NULL, bootFileSpec, &flags, &time); 
					if (ret == -1)
					{
						// No alternate location found, using the original kernel image path.
						strcpy(bootFileSpec, bootInfo->bootFile);
					}
				}
			}
			
			if ((checkOSVersion("10.7")) || (checkOSVersion("10.8")))
			{
				//Lion, dont load kernel if haz cache
				if (!trycache) 
				{
					verbose("Loading kernel %s\n", bootFileSpec);
					ret = LoadThinFatFile(bootFileSpec, &binary);
					if (ret <= 0 && archCpuType == CPU_TYPE_X86_64) 
					{
						archCpuType = CPU_TYPE_I386;
						ret = LoadThinFatFile(bootFileSpec, &binary);				
					}
				} 
				else ret = 1;
			} 
			else 
			{
				//Snow Leopard or older
				verbose("Loading kernel %s\n", bootFileSpec);
				ret = LoadThinFatFile(bootFileSpec, &binary);
				if (ret <= 0 && archCpuType == CPU_TYPE_X86_64) 
				{
					archCpuType = CPU_TYPE_I386;
					ret = LoadThinFatFile(bootFileSpec, &binary);				
				}
			}
		} while (0);
		
		clearActivityIndicator();
		
#if DEBUG
		printf("Pausing...");
		sleep(8);
#endif
		
		if (ret <= 0) {
			printf("Can't find %s\n", bootFile);
			
			sleep(1);
			
			if (gBootFileType == kNetworkDeviceType) {
				// Return control back to PXE. Don't unload PXE base code.
				gUnloadPXEOnExit = false;
				break;
			}
		} else {
			/* Won't return if successful. */
			ret = ExecKernel(binary);
		}
	}
	
	// chainboot
	if (status == 1) {
		// if we are already in graphics-mode,
		if (getVideoMode() == GRAPHICS_MODE) {
			setVideoMode(VGA_TEXT_MODE, 0); // switch back to text mode.
		}
	}
	
	if ((gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit) {
		nbpUnloadBaseCode();
	}
}
Esempio n. 17
0
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");
		}
Esempio n. 18
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;
}
Esempio n. 19
0
/*
 * Calculates the FSB and CPU frequencies using specific MSRs for each CPU
 * - multi. is read from a specific MSR. In the case of Intel, there is:
 *	   a max multi. (used to calculate the FSB freq.),
 *	   and a current multi. (used to calculate the CPU freq.)
 * - fsbFrequency = tscFrequency / multi
 * - cpuFrequency = fsbFrequency * multi
 */
void scan_cpu(PlatformInfo_t *p)
{
	uint64_t	tscFrequency = 0;
	uint64_t	fsbFrequency = 0;
	uint64_t	cpuFrequency = 0;
	uint64_t	msr = 0;
	uint64_t	flex_ratio = 0;
	uint32_t	max_ratio = 0;
	uint32_t	min_ratio = 0;
	uint8_t		bus_ratio_max = 0;
	uint8_t		currdiv = 0;
	uint8_t		currcoef = 0;
	uint8_t		maxdiv = 0;
	uint8_t		maxcoef = 0;
	const char	*newratio;
	int		len = 0;
	int		myfsb = 0;
	uint8_t		bus_ratio_min = 0;
	uint32_t	reg[4];
	char		str[128];

	/* get cpuid values */
	do_cpuid(0x00000000, p->CPU.CPUID[CPUID_0]);
	do_cpuid(0x00000001, p->CPU.CPUID[CPUID_1]);

	do_cpuid(0x00000002, p->CPU.CPUID[CPUID_2]);
	do_cpuid(0x00000003, p->CPU.CPUID[CPUID_3]);
	do_cpuid2(0x00000004, 0, p->CPU.CPUID[CPUID_4]);

	do_cpuid(0x80000000, p->CPU.CPUID[CPUID_80]);
	if (p->CPU.CPUID[CPUID_0][0] >= 0x5) {
		do_cpuid(5,  p->CPU.CPUID[CPUID_5]);
	}
	if (p->CPU.CPUID[CPUID_0][0] >= 6) {
		do_cpuid(6, p->CPU.CPUID[CPUID_6]);
	}
	if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 8) {
		do_cpuid(0x80000008, p->CPU.CPUID[CPUID_88]);
		do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);
	} else if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 1) {
		do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);
	}

// #if DEBUG_CPU
	{
		int		i;
		DBG("CPUID Raw Values:\n");
		for (i = 0; i < CPUID_MAX; i++) {
			DBG("%02d: %08x-%08x-%08x-%08x\n", i,
				   p->CPU.CPUID[i][0], p->CPU.CPUID[i][1],
				   p->CPU.CPUID[i][2], p->CPU.CPUID[i][3]);
		}
	}
// #endif

/*
    EAX (Intel):
    31    28 27            20 19    16 1514 1312 11     8 7      4 3      0
    +--------+----------------+--------+----+----+--------+--------+--------+
    |########|Extended family |Extmodel|####|type|familyid|  model |stepping|
    +--------+----------------+--------+----+----+--------+--------+--------+

    EAX (AMD):
    31    28 27            20 19    16 1514 1312 11     8 7      4 3      0
    +--------+----------------+--------+----+----+--------+--------+--------+
    |########|Extended family |Extmodel|####|####|familyid|  model |stepping|
    +--------+----------------+--------+----+----+--------+--------+--------+
*/

	p->CPU.Vendor		= p->CPU.CPUID[CPUID_0][1];
	p->CPU.Signature	= p->CPU.CPUID[CPUID_1][0];
	p->CPU.Stepping		= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 3, 0);	// stepping = cpu_feat_eax & 0xF;
	p->CPU.Model		= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 7, 4);	// model = (cpu_feat_eax >> 4) & 0xF;
	p->CPU.Family		= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 11, 8);	// family = (cpu_feat_eax >> 8) & 0xF;
	//p->CPU.Type		= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 13, 12);	// type = (cpu_feat_eax >> 12) & 0x3;
	p->CPU.ExtModel		= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 19, 16);	// ext_model = (cpu_feat_eax >> 16) & 0xF;
	p->CPU.ExtFamily	= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 27, 20);	// ext_family = (cpu_feat_eax >> 20) & 0xFF;

	p->CPU.Model += (p->CPU.ExtModel << 4);

	if (p->CPU.Vendor == CPUID_VENDOR_INTEL)
	{
		/*
		 * Find the number of enabled cores and threads
		 * (which determines whether SMT/Hyperthreading is active).
		 */
		switch (p->CPU.Model)
		{
			case CPU_MODEL_NEHALEM:
			case CPU_MODEL_FIELDS:
			case CPU_MODEL_DALES:
			case CPU_MODEL_NEHALEM_EX:
			case CPU_MODEL_JAKETOWN:
			case CPU_MODEL_SANDYBRIDGE:
			case CPU_MODEL_IVYBRIDGE:
			case CPU_MODEL_HASWELL:
			case CPU_MODEL_HASWELL_SVR:
			//case CPU_MODEL_HASWELL_H:
			case CPU_MODEL_HASWELL_ULT:
			case CPU_MODEL_CRYSTALWELL:
				msr = rdmsr64(MSR_CORE_THREAD_COUNT);
				p->CPU.NoCores		= (uint8_t)bitfield((uint32_t)msr, 31, 16);
				p->CPU.NoThreads	= (uint8_t)bitfield((uint32_t)msr, 15,  0);
				break;

			case CPU_MODEL_DALES_32NM:
			case CPU_MODEL_WESTMERE:
			case CPU_MODEL_WESTMERE_EX:
				msr = rdmsr64(MSR_CORE_THREAD_COUNT);
				p->CPU.NoCores		= (uint8_t)bitfield((uint32_t)msr, 19, 16);
				p->CPU.NoThreads	= (uint8_t)bitfield((uint32_t)msr, 15,  0);
				break;

			default:
				p->CPU.NoCores = 0;
				break;
		} // end switch
	}

	if (p->CPU.NoCores == 0)
	{
		p->CPU.NoCores		= (uint8_t)(p->CPU.CoresPerPackage & 0xff);
		p->CPU.NoThreads	= (uint8_t)(p->CPU.LogicalPerPackage & 0xff);
	}

	/* get BrandString (if supported) */
	/* Copyright: from Apple's XNU cpuid.c */
	if (p->CPU.CPUID[CPUID_80][0] > 0x80000004)
	{
		char	 *s;
		bzero(str, 128);
		/*
		 * The BrandString 48 bytes (max), guaranteed to
		 * be NULL terminated.
		 */
		do_cpuid(0x80000002, reg);
		memcpy(&str[0], (char *)reg, 16);
		do_cpuid(0x80000003, reg);
		memcpy(&str[16], (char *)reg, 16);
		do_cpuid(0x80000004, reg);
		memcpy(&str[32], (char *)reg, 16);
		for (s = str; *s != '\0'; s++)
		{
			if (*s != ' ')
			{
				break;
			}
		}
		strlcpy(p->CPU.BrandString, s, 48);

		if (!strncmp(p->CPU.BrandString, CPU_STRING_UNKNOWN, MIN(sizeof(p->CPU.BrandString), strlen(CPU_STRING_UNKNOWN) + 1)))
		{
			/*
			 * This string means we have a firmware-programmable brand string,
			 * and the firmware couldn't figure out what sort of CPU we have.
			 */
			p->CPU.BrandString[0] = '\0';
		}
		p->CPU.BrandString[47] = '\0';
//		DBG("Brandstring = %s\n", p->CPU.BrandString);
	}

	//workaround for N270. I don't know why it detected wrong
	// MSR is *NOT* available on the Intel Atom CPU
	if ((p->CPU.Model == CPU_MODEL_ATOM) && (strstr(p->CPU.BrandString, "270")))
	{
		p->CPU.NoCores		= 1;
		p->CPU.NoThreads	= 2;
	}

	if (p->CPU.Vendor == CPUID_VENDOR_AMD)
	{
		p->CPU.NoThreads	= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16);
		p->CPU.NoCores		= (uint8_t)bitfield(p->CPU.CPUID[CPUID_88][2], 7, 0) + 1;
	}

	/* setup features */
	if ((bit(23) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_MMX;
	}
	if ((bit(25) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE;
	}
	if ((bit(26) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE2;
	}
	if ((bit(0) & p->CPU.CPUID[CPUID_1][2]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE3;
	}
	if ((bit(19) & p->CPU.CPUID[CPUID_1][2]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE41;
	}
	if ((bit(20) & p->CPU.CPUID[CPUID_1][2]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE42;
	}
	if ((bit(29) & p->CPU.CPUID[CPUID_81][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_EM64T;
	}
	if ((bit(5) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_MSR;
	}
	//if ((bit(28) & p->CPU.CPUID[CPUID_1][3]) != 0) {
	if (p->CPU.NoThreads > p->CPU.NoCores) {
		p->CPU.Features |= CPU_FEATURE_HTT;
	}

	tscFrequency = measure_tsc_frequency();
	DBG("cpu freq classic = 0x%016llx\n", tscFrequency);
	/* if usual method failed */
	if ( tscFrequency < 1000 )	//TEST
	{
		tscFrequency = timeRDTSC() * 20;//measure_tsc_frequency();
		// DBG("cpu freq timeRDTSC = 0x%016llx\n", tscFrequency);
	} else {
		// DBG("cpu freq timeRDTSC = 0x%016llxn", timeRDTSC() * 20);
	}

	fsbFrequency = 0;
	cpuFrequency = 0;

	if (p->CPU.Vendor == CPUID_VENDOR_INTEL && ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0c) || (p->CPU.Family == 0x0f && p->CPU.Model >= 0x03))) {
		int intelCPU = p->CPU.Model;
		if (p->CPU.Family == 0x06) {
			/* Nehalem CPU model */
			switch (p->CPU.Model) {
				case CPU_MODEL_NEHALEM:
				case CPU_MODEL_FIELDS:
				case CPU_MODEL_DALES:
				case CPU_MODEL_DALES_32NM:
				case CPU_MODEL_WESTMERE:
				case CPU_MODEL_NEHALEM_EX:
				case CPU_MODEL_WESTMERE_EX:
/* --------------------------------------------------------- */
				case CPU_MODEL_SANDYBRIDGE:
				case CPU_MODEL_JAKETOWN:
				case CPU_MODEL_IVYBRIDGE_XEON:
				case CPU_MODEL_IVYBRIDGE:
				case CPU_MODEL_HASWELL:
				case CPU_MODEL_HASWELL_SVR:

				case CPU_MODEL_HASWELL_ULT:
				case CPU_MODEL_CRYSTALWELL:
/* --------------------------------------------------------- */
					msr = rdmsr64(MSR_PLATFORM_INFO);
					DBG("msr(%d): platform_info %08x\n", __LINE__, bitfield(msr, 31, 0));
					bus_ratio_max = bitfield(msr, 15, 8);
					bus_ratio_min = bitfield(msr, 47, 40); //valv: not sure about this one (Remarq.1)
					msr = rdmsr64(MSR_FLEX_RATIO);
					DBG("msr(%d): flex_ratio %08x\n", __LINE__, bitfield(msr, 31, 0));
					if (bitfield(msr, 16, 16))
					{
						flex_ratio = bitfield(msr, 15, 8);
						/* bcc9: at least on the gigabyte h67ma-ud2h,
						 where the cpu multipler can't be changed to
						 allow overclocking, the flex_ratio msr has unexpected (to OSX)
						 contents.	These contents cause mach_kernel to
						 fail to compute the bus ratio correctly, instead
						 causing the system to crash since tscGranularity
						 is inadvertently set to 0.
						 */
						if (flex_ratio == 0)
						{
							/* Clear bit 16 (evidently the presence bit) */
							wrmsr64(MSR_FLEX_RATIO, (msr & 0xFFFFFFFFFFFEFFFFULL));
							msr = rdmsr64(MSR_FLEX_RATIO);
							DBG("Unusable flex ratio detected. Patched MSR now %08x\n", bitfield(msr, 31, 0));
						}
						else
						{
							if (bus_ratio_max > flex_ratio)
							{
								bus_ratio_max = flex_ratio;
							}
						}
					}

					if (bus_ratio_max)
					{
						fsbFrequency = (tscFrequency / bus_ratio_max);
					}

					//valv: Turbo Ratio Limit
					if ((intelCPU != 0x2e) && (intelCPU != 0x2f))
					{
						msr = rdmsr64(MSR_TURBO_RATIO_LIMIT);

						cpuFrequency = bus_ratio_max * fsbFrequency;
						max_ratio = bus_ratio_max * 10;
					}
					else
					{
						cpuFrequency = tscFrequency;
					}
					if ((getValueForKey(kbusratio, &newratio, &len, &bootInfo->chameleonConfig)) && (len <= 4))
					{
						max_ratio = atoi(newratio);
						max_ratio = (max_ratio * 10);
						if (len >= 3)
						{
							max_ratio = (max_ratio + 5);
						}

						verbose("Bus-Ratio: min=%d, max=%s\n", bus_ratio_min, newratio);

						// extreme overclockers may love 320 ;)
						if ((max_ratio >= min_ratio) && (max_ratio <= 320))
						{
							cpuFrequency = (fsbFrequency * max_ratio) / 10;
							if (len >= 3)
							{
								maxdiv = 1;
							}
							else
							{
								maxdiv = 0;
							}
						}
						else
						{
							max_ratio = (bus_ratio_max * 10);
						}
					}
					//valv: to be uncommented if Remarq.1 didn't stick
					/*if (bus_ratio_max > 0) bus_ratio = flex_ratio;*/
					p->CPU.MaxRatio = max_ratio;
					p->CPU.MinRatio = min_ratio;

				myfsb = fsbFrequency / 1000000;
				verbose("Sticking with [BCLK: %dMhz, Bus-Ratio: %d]\n", myfsb, max_ratio/10);  // Bungo: fixed wrong Bus-Ratio readout
				currcoef = bus_ratio_max;

				break;

			default:
				msr = rdmsr64(MSR_IA32_PERF_STATUS);
				DBG("msr(%d): ia32_perf_stat 0x%08x\n", __LINE__, bitfield(msr, 31, 0));
				currcoef = bitfield(msr, 12, 8);  // Bungo: reverted to 2263 state because of wrong old CPUs freq. calculating
				/* Non-integer bus ratio for the max-multi*/
				maxdiv = bitfield(msr, 46, 46);
				/* Non-integer bus ratio for the current-multi (undocumented)*/
				currdiv = bitfield(msr, 14, 14);

				// This will always be model >= 3
				if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0e) || (p->CPU.Family == 0x0f)) {
					/* On these models, maxcoef defines TSC freq */
					maxcoef = bitfield(msr, 44, 40);
				} else {
					/* On lower models, currcoef defines TSC freq */
					/* XXX */
					maxcoef = currcoef;
				}

				if (maxcoef) {
					if (maxdiv) {
						fsbFrequency = ((tscFrequency * 2) / ((maxcoef * 2) + 1));
					} else {
						fsbFrequency = (tscFrequency / maxcoef);
					}
					if (currdiv) {
						cpuFrequency = (fsbFrequency * ((currcoef * 2) + 1) / 2);
					} else {
						cpuFrequency = (fsbFrequency * currcoef);
					}
					DBG("max: %d%s current: %d%s\n", maxcoef, maxdiv ? ".5" : "",currcoef, currdiv ? ".5" : "");
				}
				break;
			}
		}
		/* Mobile CPU */
		if (rdmsr64(MSR_IA32_PLATFORM_ID) & (1<<28)) {
			p->CPU.Features |= CPU_FEATURE_MOBILE;
		}
	} else if ((p->CPU.Vendor == CPUID_VENDOR_AMD) && (p->CPU.Family == 0x0f)) {
		switch(p->CPU.ExtFamily) {
			case 0x00: /* K8 */
				msr = rdmsr64(K8_FIDVID_STATUS);
				maxcoef = bitfield(msr, 21, 16) / 2 + 4;
				currcoef = bitfield(msr, 5, 0) / 2 + 4;
				break;

			case 0x01: /* K10 */
				msr = rdmsr64(K10_COFVID_STATUS);
				do_cpuid2(0x00000006, 0, p->CPU.CPUID[CPUID_6]);
				// EffFreq: effective frequency interface
				if (bitfield(p->CPU.CPUID[CPUID_6][2], 0, 0) == 1) {
					//uint64_t mperf = measure_mperf_frequency();
					uint64_t aperf = measure_aperf_frequency();
					cpuFrequency = aperf;
				}
				// NOTE: tsc runs at the maccoeff (non turbo)
				//			*not* at the turbo frequency.
				maxcoef	 = bitfield(msr, 54, 49) / 2 + 4;
				currcoef = bitfield(msr, 5, 0) + 0x10;
				currdiv = 2 << bitfield(msr, 8, 6);

				break;

			case 0x05: /* K14 */
				msr = rdmsr64(K10_COFVID_STATUS);
				currcoef  = (bitfield(msr, 54, 49) + 0x10) << 2;
				currdiv = (bitfield(msr, 8, 4) + 1) << 2;
				currdiv += bitfield(msr, 3, 0);

				break;

			case 0x02: /* K11 */
				// not implimented
				break;
		}

		if (maxcoef) {
			if (currdiv) {
				if (!currcoef) {
					currcoef = maxcoef;
				}

				if (!cpuFrequency) {
					fsbFrequency = ((tscFrequency * currdiv) / currcoef);
				} else {
					fsbFrequency = ((cpuFrequency * currdiv) / currcoef);
				}
				DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv);
			} else {
				if (!cpuFrequency) {
					fsbFrequency = (tscFrequency / maxcoef);
				} else {
					fsbFrequency = (cpuFrequency / maxcoef);
				}
				DBG("%d\n", currcoef);
			}
		} else if (currcoef) {
			if (currdiv) {
				fsbFrequency = ((tscFrequency * currdiv) / currcoef);
				DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv);
			} else {
				fsbFrequency = (tscFrequency / currcoef);
				DBG("%d\n", currcoef);
			}
		}
		if (!cpuFrequency) cpuFrequency = tscFrequency;
	}
	
#if 0
	if (!fsbFrequency) {
		fsbFrequency = (DEFAULT_FSB * 1000);
		cpuFrequency = tscFrequency;
		DBG("0 ! using the default value for FSB !\n");
	}

	DBG("cpu freq = 0x%016llxn", timeRDTSC() * 20);

#endif

	p->CPU.MaxCoef = maxcoef;
	p->CPU.MaxDiv = maxdiv;
	p->CPU.CurrCoef = currcoef;
	p->CPU.CurrDiv = currdiv;
	p->CPU.TSCFrequency = tscFrequency;
	p->CPU.FSBFrequency = fsbFrequency;
	p->CPU.CPUFrequency = cpuFrequency;

	// keep formatted with spaces instead of tabs
	DBG("\n---------------------------------------------\n");
   	DBG("------------------ CPU INFO -----------------\n");
	DBG("---------------------------------------------\n");
	DBG("Brand String:            %s\n",                 p->CPU.BrandString); // Processor name (BIOS)
	DBG("Vendor:                  0x%x\n",               p->CPU.Vendor); // Vendor ex: GenuineIntel
	DBG("Family:                  0x%x\n",               p->CPU.Family); // Family ex: 6 (06h)
	DBG("ExtFamily:               0x%x\n",               p->CPU.ExtFamily);
	DBG("Signature:               %x\n",                 p->CPU.Signature); // CPUID signature
	DBG("Model:                   0x%x\n",               p->CPU.Model); // Model ex: 37 (025h)
	DBG("ExtModel:                0x%x\n",               p->CPU.ExtModel);
	DBG("Stepping:                0x%x\n",               p->CPU.Stepping); // Stepping ex: 5 (05h)
	DBG("MaxCoef:                 0x%x\n",               p->CPU.MaxCoef);
	DBG("CurrCoef:                0x%x\n",               p->CPU.CurrCoef);
	DBG("MaxDiv:                  0x%x\n",               p->CPU.MaxDiv);
	DBG("CurrDiv:                 0x%x\n",               p->CPU.CurrDiv);
	DBG("TSCFreq:                 %dMHz\n",              p->CPU.TSCFrequency / 1000000);
	DBG("FSBFreq:                 %dMHz\n",              p->CPU.FSBFrequency / 1000000);
	DBG("CPUFreq:                 %dMHz\n",              p->CPU.CPUFrequency / 1000000);
	DBG("Cores:                   %d\n",                 p->CPU.NoCores); // Cores
	DBG("Logical processor:       %d\n",                 p->CPU.NoThreads); // Logical procesor
	DBG("Features:                0x%08x\n",             p->CPU.Features);

	DBG("\n---------------------------------------------\n");
#if DEBUG_CPU
	pause();
#endif
}
Esempio n. 20
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;
}
Esempio n. 21
0
/** Compute necessary space requirements for new smbios */
static struct SMBEntryPoint *smbios_dry_run(struct SMBEntryPoint *origsmbios)
{
	struct SMBEntryPoint	*ret;
	char			*smbiostables;
	char			*tablesptr;
	int			origsmbiosnum;
	int			i, j;
	int			tablespresent[256];
	bool			do_auto=true;

	bzero(tablespresent, sizeof(tablespresent));

	getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig);

	ret = (struct SMBEntryPoint *)AllocateKernelMemory(sizeof(struct SMBEntryPoint));
	if (origsmbios) {
		smbiostables = (char *)origsmbios->dmi.tableAddress;
		origsmbiosnum = origsmbios->dmi.structureCount;
	} else {
		smbiostables = NULL;
		origsmbiosnum = 0;
	}

	// _SM_
	ret->anchor[0] = 0x5f;
	ret->anchor[1] = 0x53;
	ret->anchor[2] = 0x4d;
	ret->anchor[3] = 0x5f; 
	ret->entryPointLength = sizeof(*ret);
	ret->majorVersion = 2;
	ret->minorVersion = 1;
	ret->maxStructureSize = 0; // will be calculated later in this function
	ret->entryPointRevision = 0;
	for (i=0;i<5;i++) {
		ret->formattedArea[i] = 0;
	}
	//_DMI_
	ret->dmi.anchor[0] = 0x5f;
	ret->dmi.anchor[1] = 0x44;
	ret->dmi.anchor[2] = 0x4d;
	ret->dmi.anchor[3] = 0x49;
	ret->dmi.anchor[4] = 0x5f;
	ret->dmi.tableLength = 0;  // will be calculated later in this function
	ret->dmi.tableAddress = 0; // will be initialized in smbios_real_run()
	ret->dmi.structureCount = 0; // will be calculated later in this function
	ret->dmi.bcdRevision = 0x21;
	tablesptr = smbiostables;

        // add stringlen of overrides to original stringlen, update maxStructure size adequately, 
        // update structure count and tablepresent[type] with count of type. 
	if (smbiostables) {
		for (i=0; i<origsmbiosnum; i++) {
			struct smbios_table_header	*cur = (struct smbios_table_header *)tablesptr;
			char				*stringsptr;
			int				stringlen;

			tablesptr += cur->length;
			stringsptr = tablesptr;
			for (; tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++);
			tablesptr += 2;
			stringlen = tablesptr - stringsptr - 1;
			if (stringlen == 1) {
				stringlen = 0;
			}
			for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
				const char	*str;
				int		size;
				char		altname[40];

				sprintf(altname, "%s_%d",smbios_properties[j].name, tablespresent[cur->type] + 1);				
				if (smbios_properties[j].table_type == cur->type &&
				    smbios_properties[j].value_type == SMSTRING &&
				    (getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig) ||
				     getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig)))
				{
					stringlen += size + 1;
				} else if (smbios_properties[j].table_type == cur->type &&
				           smbios_properties[j].value_type == SMSTRING &&
				           do_auto && smbios_properties[j].auto_str)
				{
					stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[cur->type])) + 1;
				}
			}
			if (stringlen == 0) {
				stringlen = 1;
			}
			stringlen++;
			if (ret->maxStructureSize < cur->length+stringlen) {
				ret->maxStructureSize=cur->length+stringlen;
			}
			ret->dmi.tableLength += cur->length+stringlen;
			ret->dmi.structureCount++;
			tablespresent[cur->type]++;
		}
	}
        // Add eventually table types whose detected count would be < required count, and update ret header with:
        // new stringlen addons, structure count, and tablepresent[type] count adequately
	for (i=0; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) {
		int	numnec=-1;
		char	buffer[40];

		sprintf(buffer, "SMtable%d", i);
		if (!getIntForKey(buffer, &numnec, &bootInfo->smbiosConfig)) {
			numnec = -1;
		}
		if (numnec==-1 && do_auto && smbios_table_descriptions[i].numfunc) {
			numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type);
		}
		while (tablespresent[smbios_table_descriptions[i].type] < numnec) {
			int	stringlen = 0;
			for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
				const char	*str;
				int		size;
				char		altname[40];

				sprintf(altname, "%s_%d",smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type] + 1);
				if (smbios_properties[j].table_type == smbios_table_descriptions[i].type &&
				    smbios_properties[j].value_type == SMSTRING &&
				    (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
				     getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)))
				{
					stringlen += size + 1;
				} else if (smbios_properties[j].table_type == smbios_table_descriptions[i].type &&
				           smbios_properties[j].value_type==SMSTRING &&
				           do_auto && smbios_properties[j].auto_str)
				{
					stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type])) + 1;
				}
			}
			if (stringlen == 0) {
				stringlen = 1;
			}
			stringlen++;
			if (ret->maxStructureSize < smbios_table_descriptions[i].len+stringlen) {
				ret->maxStructureSize = smbios_table_descriptions[i].len + stringlen;
			}
			ret->dmi.tableLength += smbios_table_descriptions[i].len + stringlen;
			ret->dmi.structureCount++;
			tablespresent[smbios_table_descriptions[i].type]++;
		}
	}
	return ret;
}
Esempio n. 22
0
//==========================================================================
// The 'main' function for the booter. Called by boot0 when booting
// from a block device, or by the network booter.
//
// arguments:
//	 biosdev - Value passed from boot1/NBP to specify the device
//			   that the booter was loaded from.
//
// If biosdev is kBIOSDevNetwork, then this function will return if
// booting was unsuccessful. This allows the PXE firmware to try the
// next boot device on its list.
void common_boot(int biosdev)
{
	bool	 		quiet;
	bool	 		firstRun = true;
	bool	 		instantMenu;
	bool	 		rescanPrompt;
	int				status;
	unsigned int	allowBVFlags = kBVFlagSystemVolume | kBVFlagForeignBoot;
	unsigned int	denyBVFlags = kBVFlagEFISystem;
	
	// Set reminder to unload the PXE base code. Neglect to unload
	// the base code will result in a hang or kernel panic.
	gUnloadPXEOnExit = true;
	
	// Record the device that the booter was loaded from.
	gBIOSDev = biosdev & kBIOSDevMask;
	
	// Initialize boot info structure.
	initKernBootStruct();
	
	initBooterLog();
	
	// Setup VGA text mode.
	// Not sure if it is safe to call setVideoMode() before the
	// config table has been loaded. Call video_mode() instead.
#if DEBUG
	printf("before video_mode\n");
#endif
	video_mode( 2 );  // 80x25 mono text mode.
#if DEBUG
	printf("after video_mode\n");
#endif
	
	// Scan and record the system's hardware information.
	scan_platform();
	
	// First get info for boot volume.
	scanBootVolumes(gBIOSDev, 0);
	bvChain = getBVChainForBIOSDev(gBIOSDev);
	setBootGlobals(bvChain);
	
	// Load boot.plist config file
	status = loadChameleonConfig(&bootInfo->chameleonConfig);
	
	if (getBoolForKey(kQuietBootKey, &quiet, &bootInfo->chameleonConfig) && quiet) {
		gBootMode |= kBootModeQuiet;
	}
	
	// Override firstRun to get to the boot menu instantly by setting "Instant Menu"=y in system config
	if (getBoolForKey(kInstantMenuKey, &instantMenu, &bootInfo->chameleonConfig) && instantMenu) {
		firstRun = false;
	}
	
	// Loading preboot ramdisk if exists.
	loadPrebootRAMDisk();
	
	// Disable rescan option by default
	gEnableCDROMRescan = false;
	
	// Enable it with Rescan=y in system config
	if (getBoolForKey(kRescanKey, &gEnableCDROMRescan, &bootInfo->chameleonConfig)
		&& gEnableCDROMRescan) {
		gEnableCDROMRescan = true;
	}
	
	// Ask the user for Rescan option by setting "Rescan Prompt"=y in system config.
	rescanPrompt = false;
	if (getBoolForKey(kRescanPromptKey, &rescanPrompt , &bootInfo->chameleonConfig)
		&& rescanPrompt && biosDevIsCDROM(gBIOSDev))
	{
		gEnableCDROMRescan = promptForRescanOption();
	}
	
	// Enable touching a single BIOS device only if "Scan Single Drive"=y is set in system config.
	if (getBoolForKey(kScanSingleDriveKey, &gScanSingleDrive, &bootInfo->chameleonConfig)
		&& gScanSingleDrive) {
		gScanSingleDrive = true;
	}
	
	// Create a list of partitions on device(s).
	if (gScanSingleDrive) {
		scanBootVolumes(gBIOSDev, &bvCount);
	} else {
		scanDisks(gBIOSDev, &bvCount);
	}
	
	// Create a separated bvr chain using the specified filters.
	bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount);
	
	gBootVolume = selectBootVolume(bvChain);
	
	// Intialize module system 
	init_module_system();
		
#if DEBUG
	printf(" Default: %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n",
			 gBootVolume, gBootVolume->biosdev, gBootVolume->part_no, gBootVolume->flags);
	printf(" bt(0,0): %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n",
			 gBIOSBootVolume, gBIOSBootVolume->biosdev, gBIOSBootVolume->part_no, gBIOSBootVolume->flags);
	getchar();
#endif
	
	useGUI = true;
	// Override useGUI default
	getBoolForKey(kGUIKey, &useGUI, &bootInfo->chameleonConfig);
	if (useGUI && initGUI())
	{
		// initGUI() returned with an error, disabling GUI.
		useGUI = false;
	}
	
	setBootGlobals(bvChain);
	
	// Parse args, load and start kernel.
	while (1)
	{
		bool		tryresume, tryresumedefault, forceresume;
		bool		useKernelCache = true; // by default try to use the prelinked kernel
		const char	*val;
		int			len, ret = -1;
		long		flags, sleeptime, time;
		void		*binary = (void *)kLoadAddr;
		
		char        bootFile[sizeof(bootInfo->bootFile)];
		char		bootFilePath[512];
		char		kernelCacheFile[512];

		// Initialize globals.
		sysConfigValid = false;
		gErrors		   = false;
		
		status = getBootOptions(firstRun);
		firstRun = false;
		if (status == -1) continue;
		 
		status = processBootOptions();
		// Status == 1 means to chainboot
		if ( status ==	1 ) break;
		// Status == -1 means that the config file couldn't be loaded or that gBootVolume is NULL
		if ( status == -1 )
		{
			// gBootVolume == NULL usually means the user hit escape.
			if (gBootVolume == NULL)
			{
				freeFilteredBVChain(bvChain);
				
				if (gEnableCDROMRescan)
					rescanBIOSDevice(gBIOSDev);
				
				bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount);
				setBootGlobals(bvChain);
				setupDeviceList(&bootInfo->themeConfig);
			}
			continue;
		}
		
		// Other status (e.g. 0) means that we should proceed with boot.
		
		// Turn off any GUI elements
		if ( bootArgs->Video.v_display == GRAPHICS_MODE )
		{
			gui.devicelist.draw = false;
			gui.bootprompt.draw = false;
			gui.menu.draw = false;
			gui.infobox.draw = false;
			gui.logo.draw = false;
			drawBackground();
			updateVRAM();
		}
		
		// Find out which version mac os we're booting.
		getOSVersion();
		
		if (platformCPUFeature(CPU_FEATURE_EM64T)) {
			archCpuType = CPU_TYPE_X86_64;
		} else {
			archCpuType = CPU_TYPE_I386;
		}
		
		if (getValueForKey(karch, &val, &len, &bootInfo->chameleonConfig)) {
			if (strncmp(val, "i386", 4) == 0) {
				archCpuType = CPU_TYPE_I386;
			}
		}
		
		if (getValueForKey(kKernelArchKey, &val, &len, &bootInfo->chameleonConfig)) {
			if (strncmp(val, "i386", 4) == 0) {
				archCpuType = CPU_TYPE_I386;
			}
		}
		
		// Notify modules that we are attempting to boot
		execute_hook("PreBoot", NULL, NULL, NULL, NULL);
		
		if (!getBoolForKey (kWake, &tryresume, &bootInfo->chameleonConfig)) {
			tryresume = true;
			tryresumedefault = true;
		} else {
			tryresumedefault = false;
		}
		
		if (!getBoolForKey (kForceWake, &forceresume, &bootInfo->chameleonConfig)) {
			forceresume = false;
		}
		
		if (forceresume) {
			tryresume = true;
			tryresumedefault = false;
		}
		
		while (tryresume) {
			const char *tmp;
			BVRef bvr;
			if (!getValueForKey(kWakeImage, &val, &len, &bootInfo->chameleonConfig))
				val = "/private/var/vm/sleepimage";
			
			// Do this first to be sure that root volume is mounted
			ret = GetFileInfo(0, val, &flags, &sleeptime);
			
			if ((bvr = getBootVolumeRef(val, &tmp)) == NULL)
				break;
			
			// Can't check if it was hibernation Wake=y is required
			if (bvr->modTime == 0 && tryresumedefault)
				break;
			
			if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat))
				break;
			
			if (!forceresume && ((sleeptime+3)<bvr->modTime)) {
#if DEBUG	
				printf ("Hibernate image is too old by %d seconds. Use ForceWake=y to override\n",
						bvr->modTime-sleeptime);
#endif				  
				break;
			}
			
			HibernateBoot((char *)val);
			break;
		}
		
		verbose("Loading Darwin %s\n", gMacOSVersion);

		getBoolForKey(kUseKernelCache, &useKernelCache, &bootInfo->chameleonConfig);
		if (useKernelCache) do {

			// Determine the name of the Kernel Cache
			if (getValueForKey(kKernelCacheKey, &val, &len, &bootInfo->bootConfig)) {
				if (val[0] == '\\')
				{
					len--;
					val++;
				}
				strlcpy(kernelCacheFile, val, len + 1);
			} else {
				kernelCacheFile[0] = 0; // Use default kernel cache file
			}

			if (gOverrideKernel && kernelCacheFile[0] == 0) {
				verbose("Using a non default kernel (%s) without specifying 'Kernel Cache' path, KernelCache will not be used\n",
						bootInfo->bootFile);
				useKernelCache = false;
				break;
			}
			if (gMKextName[0] != 0) {
				verbose("Using a specific MKext Cache (%s), KernelCache will not be used\n",
						gMKextName);
				useKernelCache = false;
				break;
			}
			if (gBootFileType != kBlockDeviceType)
				useKernelCache = false;

		} while(0);
		
		do {
			if (useKernelCache) {
				ret = LoadKernelCache(kernelCacheFile, &binary);
				if (ret >= 0)
					break;
			}

			bool bootFileWithDevice = false;
			// Check if bootFile start with a device ex: bt(0,0)/Extra/mach_kernel
			if (strncmp(bootInfo->bootFile,"bt(",3) == 0 ||
				strncmp(bootInfo->bootFile,"hd(",3) == 0 ||
				strncmp(bootInfo->bootFile,"rd(",3) == 0)
				bootFileWithDevice = true;

			// bootFile must start with a / if it not start with a device name
			if (!bootFileWithDevice && (bootInfo->bootFile)[0] != '/')
				sprintf(bootFile, "/%s", bootInfo->bootFile); // append a leading /
			else
				strlcpy(bootFile, bootInfo->bootFile, sizeof(bootFile));

			// Try to load kernel image from alternate locations on boot helper partitions.
			ret = -1;
			if ((gBootVolume->flags & kBVFlagBooter) && !bootFileWithDevice) {
				sprintf(bootFilePath, "com.apple.boot.P%s", bootFile);
				ret = GetFileInfo(NULL, bootFilePath, &flags, &time);
				if (ret == -1)
				{
					sprintf(bootFilePath, "com.apple.boot.R%s", bootFile);
					ret = GetFileInfo(NULL, bootFilePath, &flags, &time);
					if (ret == -1)
					{
						sprintf(bootFilePath, "com.apple.boot.S%s", bootFile);
						ret = GetFileInfo(NULL, bootFilePath, &flags, &time);
					}
				}
			}
			if (ret == -1) {
				// No alternate location found, using the original kernel image path.
				strlcpy(bootFilePath, bootFile,sizeof(bootFilePath));
			}
			
			verbose("Loading kernel %s\n", bootFilePath);
			ret = LoadThinFatFile(bootFilePath, &binary);
			if (ret <= 0 && archCpuType == CPU_TYPE_X86_64)
			{
				archCpuType = CPU_TYPE_I386;
				ret = LoadThinFatFile(bootFilePath, &binary);
			}
		} while (0);
		
		clearActivityIndicator();
		
#if DEBUG
		printf("Pausing...");
		sleep(8);
#endif
		
		if (ret <= 0) {
			printf("Can't find %s\n", bootFile);
			sleep(1);
			
			if (gBootFileType == kNetworkDeviceType) {
				// Return control back to PXE. Don't unload PXE base code.
				gUnloadPXEOnExit = false;
				break;
			}
			pause();

		} else {
			/* Won't return if successful. */
			ret = ExecKernel(binary);
		}
	}
	
	// chainboot
	if (status == 1) {
		// if we are already in graphics-mode,
		if (getVideoMode() == GRAPHICS_MODE) {
			setVideoMode(VGA_TEXT_MODE, 0); // switch back to text mode.
		}
	}
	
	if ((gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit) {
		nbpUnloadBaseCode();
	}
}
Esempio n. 23
0
/* Compute necessary space requirements for new smbios */
struct SMBEntryPoint *
smbios_dry_run (struct SMBEntryPoint * origsmbios)
{
	struct SMBEntryPoint *ret;
	char *smbiostables=0;
	char *tablesptr;
	int origsmbiosnum=0;
	int i, j;
	int tablespresent[256];
	BOOL do_auto=1;

	getBoolForKey("SMBIOSdefaults",&do_auto,&bootInfo->bootConfig);

	for (i=0;i<256;i++)
		tablespresent[i]=0;
	ret=(struct SMBEntryPoint *)AllocateKernelMemory(sizeof (struct SMBEntryPoint));
	if (origsmbios)
	{
		smbiostables=(char *)origsmbios->dmi.tableAddress;
		origsmbiosnum=origsmbios->dmi.structureCount;
    }
	// _SM_
	ret->anchor[0]=0x5f;
	ret->anchor[1]=0x53;
	ret->anchor[2]=0x4d;
	ret->anchor[3]=0x5f; 
	ret->entryPointLength=sizeof (*ret);
	ret->majorVersion=2;
	ret->minorVersion=1;
	ret->maxStructureSize=0; 
	ret->entryPointRevision=0;
	for (i=0;i<5;i++)
		ret->formattedArea[i]=0;
	//_DMI_
	ret->dmi.anchor[0]=0x5f;
	ret->dmi.anchor[1]=0x44;
	ret->dmi.anchor[2]=0x4d;
	ret->dmi.anchor[3]=0x49;
	ret->dmi.anchor[4]=0x5f;
	ret->dmi.tableLength=0; 
	ret->dmi.tableAddress=0; 
	ret->dmi.structureCount=0; 
	ret->dmi.bcdRevision=0x21;
	tablesptr=smbiostables;
	if (smbiostables)
		for (i=0;i<origsmbiosnum;i++)
		{
			struct smbios_table_header *cur
			=(struct smbios_table_header *) tablesptr;
			char *stringsptr;
			int stringlen;
			tablesptr+=cur->length;
			stringsptr=tablesptr;
			for (;tablesptr[0]!=0 || tablesptr[1]!=0;tablesptr++);
			tablesptr+=2;
			stringlen=tablesptr-stringsptr-1;
			if (stringlen==1)
				stringlen=0;
			for (j=0;j<sizeof (smbios_properties)/sizeof(smbios_properties[0]);
				 j++)
			{
				const char *str;
				int size;
				char altname[40];
				sprintf (altname, "%s_%d",smbios_properties[j].name,
						 tablespresent[cur->type]+1);				
				if (smbios_properties[j].table_type==cur->type 
					&& smbios_properties[j].value_type==SMSTRING
					&& (getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)
					    || getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig)))
					stringlen+=size+1;
				else if (smbios_properties[j].table_type==cur->type 
						 && smbios_properties[j].value_type==SMSTRING
						 && do_auto && smbios_properties[j].auto_str)
					stringlen+=strlen(smbios_properties[j].auto_str(smbios_properties[j].name,tablespresent[cur->type]))+1;
			}
			if (stringlen==0)
				stringlen=1;
			stringlen++;
			if (ret->maxStructureSize<cur->length+stringlen)
				ret->maxStructureSize=cur->length+stringlen;
			ret->dmi.tableLength+=cur->length+stringlen;
			ret->dmi.structureCount++;
			tablespresent[cur->type]++;
		}
	for (i=0;i<sizeof (smbios_table_descriptions)
		 /sizeof(smbios_table_descriptions[0]);i++)
	{
		int numnec=-1;
		char buffer[40];
		sprintf (buffer, "SMtable%d", i);
		if (!getIntForKey(buffer,&numnec,&bootInfo->smbiosConfig))
			numnec=-1;
		if (numnec==-1 && do_auto && smbios_table_descriptions[i].numfunc)
			numnec=smbios_table_descriptions[i].numfunc (smbios_table_descriptions[i].type);
		
		while (tablespresent[smbios_table_descriptions[i].type]<numnec)
		{
			int stringlen=0;
			for (j=0;j<sizeof (smbios_properties)/sizeof(smbios_properties[0]);
				 j++)
			{
				const char *str;
				int size;
				char altname[40];
				sprintf (altname, "%s_%d",smbios_properties[j].name,
						 tablespresent[smbios_table_descriptions[i].type]+1);
				if (smbios_properties[j].table_type
					==smbios_table_descriptions[i].type 
					&& smbios_properties[j].value_type==SMSTRING
					&& (getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig)
						|| getValueForKey(smbios_properties[j].name,&str, &size, &bootInfo->smbiosConfig)))
					stringlen+=size+1; 
				else if (smbios_properties[j].table_type
						 ==smbios_table_descriptions[i].type 
						 && smbios_properties[j].value_type==SMSTRING
						 && do_auto && smbios_properties[j].auto_str)
					stringlen+=strlen(smbios_properties[j].auto_str
									  (smbios_properties[j].name,
									   tablespresent[smbios_table_descriptions[i].type]))+1;
			}
			if (stringlen==0)
				stringlen=1;
			stringlen++;
			if (ret->maxStructureSize<smbios_table_descriptions[i].len+stringlen)
				ret->maxStructureSize=smbios_table_descriptions[i].len+stringlen;
			ret->dmi.tableLength+=smbios_table_descriptions[i].len+stringlen;
			ret->dmi.structureCount++;
			tablespresent[smbios_table_descriptions[i].type]++;
		}
	}
	return ret;
}
Esempio n. 24
0
void loadThemeValues(config_file_t *theme, bool overide)
{
	unsigned int screen_width  = gui.screen.width;
	unsigned int screen_height = gui.screen.height;
	unsigned int pixel;
	int	alpha;				// transparency level 0 (obligue) - 255 (transparent)
	uint32_t color;			// color value formatted RRGGBB
	int val, len;
	const char *string;	

	/*
	 * Parse screen parameters
	 */
	if(getColorForKey("screen_bgcolor", &color, theme ))
		gui.screen.bgcolor = (color & 0x00FFFFFF);

	if(getIntForKey("screen_textmargin_h", &val, theme))
		gui.screen.hborder = MIN( gui.screen.width , val );

	if(getIntForKey("screen_textmargin_v", &val, theme))
		gui.screen.vborder = MIN( gui.screen.height , val );

	/*
	 * Parse background parameters
	 */
	if(getDimensionForKey("background_pos_x", &pixel, theme, screen_width , images[iBackground].image->width ) )
		gui.background.pos.x = pixel;

	if(getDimensionForKey("background_pos_y", &pixel, theme, screen_height , images[iBackground].image->height ) )
		gui.background.pos.y = pixel;

	/*
	 * Parse logo parameters
	 */
	if(getDimensionForKey("logo_pos_x", &pixel, theme, screen_width , images[iLogo].image->width ) )
		gui.logo.pos.x = pixel;

	if(getDimensionForKey("logo_pos_y", &pixel, theme, screen_height , images[iLogo].image->height ) )
		gui.logo.pos.y = pixel;

	/*
	 * Parse progress bar parameters
	 */
	if(getDimensionForKey("progressbar_pos_x", &pixel, theme, screen_width , 0 ) )
		gui.progressbar.pos.x = pixel;

	if(getDimensionForKey("progressbar_pos_y", &pixel, theme, screen_height , 0 ) )
		gui.progressbar.pos.y = pixel;

	/*
	 * Parse countdown text parameters
	 */
	if(getDimensionForKey("countdown_pos_x", &pixel, theme, screen_width , 0 ) )
		gui.countdown.pos.x = pixel;

	if(getDimensionForKey("countdown_pos_y", &pixel, theme, screen_height , 0 ) )
		gui.countdown.pos.y = pixel;

	/*
	 * Parse devicelist parameters
	 */
	if(getIntForKey("devices_max_visible", &val, theme ))
		gui.maxdevices = MIN( val, gDeviceCount );

	if(getIntForKey("devices_iconspacing", &val, theme ))
		gui.devicelist.iconspacing = val;

	// check layout for horizontal or vertical
	gui.layout = HorizontalLayout;
	if(getValueForKey( "devices_layout", &string, &len, theme)) {
		if (!strcmp (string, "vertical")) {
			gui.layout = VerticalLayout;
		}
	}

	switch (gui.layout) {
	case VerticalLayout:
		gui.devicelist.height = ((images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing) * MIN(gui.maxdevices, gDeviceCount) + (images[iDeviceScrollPrev].image->height + images[iDeviceScrollNext].image->height) + gui.devicelist.iconspacing);
		gui.devicelist.width  = (images[iSelection].image->width + gui.devicelist.iconspacing);

		if(getDimensionForKey("devices_pos_x", &pixel, theme, gui.screen.width , images[iSelection].image->width ) )
			gui.devicelist.pos.x = pixel;

		if(getDimensionForKey("devices_pos_y", &pixel, theme, gui.screen.height , gui.devicelist.height ) )
			gui.devicelist.pos.y = pixel;
		break;
		
	case HorizontalLayout:
	default:
		gui.devicelist.width = ((images[iSelection].image->width + gui.devicelist.iconspacing) * MIN(gui.maxdevices, gDeviceCount) + (images[iDeviceScrollPrev].image->width + images[iDeviceScrollNext].image->width) + gui.devicelist.iconspacing);
		gui.devicelist.height = (images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing);

		if(getDimensionForKey("devices_pos_x", &pixel, theme, gui.screen.width , gui.devicelist.width ) )
			gui.devicelist.pos.x = pixel;
		else
			gui.devicelist.pos.x = ( gui.screen.width - gui.devicelist.width ) / 2;
		
		if(getDimensionForKey("devices_pos_y", &pixel, theme, gui.screen.height , images[iSelection].image->height ) )
			gui.devicelist.pos.y = pixel;
		else
			gui.devicelist.pos.y = ( gui.screen.height - gui.devicelist.height ) / 2;
		break;
	}

	if(getColorForKey("devices_bgcolor", &color, theme))
		gui.devicelist.bgcolor = (color & 0x00FFFFFF);

	if(getIntForKey("devices_transparency", &alpha, theme))
		gui.devicelist.bgcolor = gui.devicelist.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);

	/*
	 * Parse infobox parameters
	 */
	if(getIntForKey("infobox_width", &val, theme))
		gui.infobox.width = MIN( screen_width , val );

	if(getIntForKey("infobox_height", &val, theme))
		gui.infobox.height = MIN( screen_height , val );

	if(getDimensionForKey("infobox_pos_x", &pixel, theme, screen_width , gui.infobox.width ) )
		gui.infobox.pos.x = pixel;

	if(getDimensionForKey("infobox_pos_y", &pixel, theme, screen_height , gui.infobox.height ) )
		gui.infobox.pos.y = pixel;

	if(getIntForKey("infobox_textmargin_h", &val, theme))
		gui.infobox.hborder = MIN( gui.infobox.width , val );

	if(getIntForKey("infobox_textmargin_v", &val, theme))
		gui.infobox.vborder = MIN( gui.infobox.height , val );

	if(getColorForKey("infobox_bgcolor", &color, theme))
		gui.infobox.bgcolor = (color & 0x00FFFFFF);

	if(getIntForKey("infobox_transparency", &alpha, theme))
		gui.infobox.bgcolor = gui.infobox.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);

	/*
	 * Parse menu parameters
	 */
	if(getDimensionForKey("menu_width", &pixel, theme, gui.screen.width , 0 ) )
		gui.menu.width = pixel;
	else
		gui.menu.width = images[iMenuSelection].image->width;

	if(getDimensionForKey("menu_height", &pixel, theme, gui.screen.height , 0 ) )
		gui.menu.height = pixel;
	else
		gui.menu.height = (infoMenuItemsCount) * images[iMenuSelection].image->height;

	if(getDimensionForKey("menu_pos_x", &pixel, theme, screen_width , gui.menu.width ) )
		gui.menu.pos.x = pixel;

	if(getDimensionForKey("menu_pos_y", &pixel, theme, screen_height , gui.menu.height ) )
		gui.menu.pos.y = pixel;

	if(getIntForKey("menu_textmargin_h", &val, theme))
		gui.menu.hborder = MIN( gui.menu.width , val );

	if(getIntForKey("menu_textmargin_v", &val, theme))
		gui.menu.vborder = MIN( gui.menu.height , val );

	if(getColorForKey("menu_bgcolor", &color, theme))
		gui.menu.bgcolor = (color & 0x00FFFFFF);

	if(getIntForKey("menu_transparency", &alpha, theme))
		gui.menu.bgcolor = gui.menu.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);		

	/*
	 * Parse bootprompt parameters
	 */
	if(getDimensionForKey("bootprompt_width", &pixel, theme, screen_width , 0 ) )
		gui.bootprompt.width = pixel;

	if(getIntForKey("bootprompt_height", &val, theme))
		gui.bootprompt.height = MIN( screen_height , val );

	if(getDimensionForKey("bootprompt_pos_x", &pixel, theme, screen_width , gui.bootprompt.width ) )
		gui.bootprompt.pos.x = pixel;

	if(getDimensionForKey("bootprompt_pos_y", &pixel, theme, screen_height , gui.bootprompt.height ) )
		gui.bootprompt.pos.y = pixel;

	if(getIntForKey("bootprompt_textmargin_h", &val, theme))
		gui.bootprompt.hborder = MIN( gui.bootprompt.width , val );

	if(getIntForKey("bootprompt_textmargin_v", &val, theme))
		gui.bootprompt.vborder = MIN( gui.bootprompt.height , val );

	if(getColorForKey("bootprompt_bgcolor", &color, theme))
		gui.bootprompt.bgcolor = (color & 0x00FFFFFF);

	if(getIntForKey("bootprompt_transparency", &alpha, theme))
		gui.bootprompt.bgcolor = gui.bootprompt.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);

	if(getColorForKey("font_small_color", &color, theme))
		gui.screen.font_small_color = (color & 0x00FFFFFF);

	if(getColorForKey("font_console_color", &color, theme))
		gui.screen.font_console_color = (color & 0x00FFFFFF);
}
Esempio n. 25
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;

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

    if (!getValueForBootKey(cp, "config", &val, &cnt)) {
      val = 0;
      cnt = 0;
    }

    // Load com.apple.Boot.plist from the selected volume
    // and use its contents to override default bootConfig.

    loadSystemConfig(&bootInfo->bootConfig);    
    loadChameleonConfig(&bootInfo->chameleonConfig);

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

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

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

	// Get config kernel flags, if not ignored.
    if (getValueForBootKey(cp, kIgnoreBootFileFlag, &val, &cnt) ||
            !getValueForKey( kKernelFlagsKey, &val, &cnt, &bootInfo->bootConfig )) {
        val = "";
        cnt = 0;
    }
    configKernelFlags = malloc(cnt + 1);
    strlcpy(configKernelFlags, val, cnt + 1);

    // boot-uuid can be set either on the command-line or in the config file
	if (!processBootArgument(kBootUUIDKey, cp, configKernelFlags, bootInfo->config,
                             &argP, &cntRemaining, gBootUUIDString, sizeof(gBootUUIDString))) {
        //
        // Try an alternate method for getting the root UUID on boot helper partitions.
        //
        if (gBootVolume->flags & kBVFlagBooter)
		{
			// Load the configuration store in the boot helper partition
			if (loadHelperConfig(&bootInfo->helperConfig) == 0)
        	{
				val = getStringForKey(kHelperRootUUIDKey, &bootInfo->helperConfig);
				if (val != NULL)
					strlcpy(gBootUUIDString, val, sizeof(gBootUUIDString));
			}
        }
        
        // Try to get the volume uuid string
		if (!strlen(gBootUUIDString) && gBootVolume->fs_getuuid)
			gBootVolume->fs_getuuid(gBootVolume, gBootUUIDString);
         
		// If we have the volume uuid add it to the commandline arguments
		if (strlen(gBootUUIDString))
			copyArgument(kBootUUIDKey, gBootUUIDString, strlen(gBootUUIDString), &argP, &cntRemaining);
	}

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

    /*
     * Removed. We don't need this anymore.
     *
    if (!processBootArgument(kPlatformKey, cp, configKernelFlags, bootInfo->config,
							 &argP, &cntRemaining, gPlatformName, sizeof(gCacheNameAdler))) {
        getPlatformName(gPlatformName);
        copyArgument(kPlatformKey, gPlatformName, strlen(gPlatformName), &argP, &cntRemaining);
    }
    */

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

    // Store the merged kernel flags and boot args.

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

	if(!shouldboot)
	{
		gVerboseMode = getValueForKey( kVerboseModeFlag, &val, &cnt, &bootInfo->chameleonConfig ) ||
			getValueForKey( kSingleUserModeFlag, &val, &cnt, &bootInfo->chameleonConfig );
		
		gBootMode = ( getValueForKey( kSafeModeFlag, &val, &cnt, &bootInfo->chameleonConfig ) ) ?
			kBootModeSafe : kBootModeNormal;

        if ( getValueForKey( kIgnoreCachesFlag, &val, &cnt, &bootInfo->chameleonConfig ) ) {
            gBootMode = kBootModeSafe;
       }
	}

	if ( getValueForKey( kMKextCacheKey, &val, &cnt, &bootInfo->bootConfig ) )
		strlcpy(gMKextName, val, cnt + 1);
	else
		gMKextName[0]=0;

    free(configKernelFlags);
    free(valueBuffer);

    return 0;
}
Esempio n. 26
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();
    }
}