Chameleon

Chameleon Commit Details

Date:2010-08-03 20:04:39 (13 years 8 months ago)
Author:Azimutz
Commit:301
Parents: 300
Message:Editing the file closer to coding_standards, specially removing all those comments with /**/ from inside functions; they are an annoyance if we need to completely comment out one of these functions. Comment correction: the code i mentioned as being pre RC3 on commit 299, is in fact pre RC4.
Changes:
M/branches/azimutz/CleanCut/i386/libsaio/fake_efi.c

File differences

branches/azimutz/CleanCut/i386/libsaio/fake_efi.c
2222
2323
2424
25
26
27
28
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
2953
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
5554
5655
5756
5857
5958
6059
61
62
63
60
61
62
6463
6564
66
6765
6866
6967
68
7069
7170
72
71
7372
7473
75
7674
7775
7876
......
8280
8381
8482
85
83
8684
8785
8886
87
8988
9089
9190
......
108107
109108
110109
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
141140
142141
143142
......
148147
149148
150149
151
152
150
151
152
153
154
155
153156
154
155
156
157157
158158
159159
......
381381
382382
383383
384
385
386
387
388
384
385
386
387
388
389389
390390
391391
......
439439
440440
441441
442
442
443
444
445
443446
444447
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
448461
449
462
463
464
450465
451
452
453
454
455
456
457
458
459
460
466
461467
468
469
462470
463
464
465
466
467
471
472
473
468474
469
470
475
476
471477
472
478
473479
474480
475
476
481
482
483
477484
478485
479486
480
487
488
489
481490
482491
483492
484
493
485494
486495
487496
488497
489
498
499
490500
491501
502
492503
493
504
505
506
507
508
509
494510
495
496
497
498
511
512
513
514
515
516
517
518
519
520
521
522
499523
500
501
502
503
504
505
524
525
526
527
506528
507
508
509
510
511
512529
513530
514
515
516
517
518
531
532
533
534
535
519536
520537
521538
522539
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
540
541
542
543
544
545
546
547
548
549
550
551
552
553
538554
539555
540556
......
545561
546562
547563
548
549
550
551
552
553
554
555
564
565
566
567
568
569
570
571
556572
557573
558574
......
567583
568584
569585
570
571
572
573
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
574610
575
576
577
578
579
580
581
582
583
584
585
586
587
611
612
613
614
615
616
617
618
619
620
621
588622
589
590
623
624
625
591626
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610627
611628
612
613
614
615
616
617
629
630
631
632
633
634
635
618636
619
637
620638
621639
622640
623641
624642
625
643
626644
627645
628
646
647
648
649
629650
630651
631652
......
647668
648669
649670
671
672
673
650674
651
652675
653676
654677
extern void setup_pci_devs(pci_dt_t *pci_dt);
/*
Modern Darwin kernels require some amount of EFI because Apple machines all
have EFI. Modifying the kernel source to not require EFI is of course
possible but would have to be maintained as a separate patch because it is
unlikely that Apple wishes to add legacy support to their kernel.
* Modern Darwin kernels require some amount of EFI because Apple machines all
* have EFI. Modifying the kernel source to not require EFI is of course
* possible but would have to be maintained as a separate patch because it is
* unlikely that Apple wishes to add legacy support to their kernel.
*
* As you can see from the Apple-supplied code in bootstruct.c, it seems that
* the intention was clearly to modify this booter to provide EFI-like structures
* to the kernel rather than modifying the kernel to handle non-EFI stuff. This
* makes a lot of sense from an engineering point of view as it means the kernel
* for the as yet unreleased EFI-only Macs could still be booted by the non-EFI
* DTK systems so long as the kernel checked to ensure the boot tables were
* filled in appropriately. Modern xnu requires a system table and a runtime
* services table and performs no checks whatsoever to ensure the pointers to
* these tables are non-NULL.Therefore, any modern xnu kernel will page fault
* early on in the boot process if the system table pointer is zero.
*
* Even before that happens, the tsc_init function in modern xnu requires the FSB
* Frequency to be a property in the /efi/platform node of the device tree or else
* it panics the bootstrap process very early on.
*
* As of this writing, the current implementation found here is good enough
* to make the currently available xnu kernel boot without modification on a
* system with an appropriate processor. With a minor source modification to
* the tsc_init function to remove the explicit check for Core or Core 2
* processors the kernel can be made to boot on other processors so long as
* the code can be executed by the processor and the machine contains the
* necessary hardware.
*/
As you can see from the Apple-supplied code in bootstruct.c, it seems that
the intention was clearly to modify this booter to provide EFI-like structures
to the kernel rather than modifying the kernel to handle non-EFI stuff. This
makes a lot of sense from an engineering point of view as it means the kernel
for the as yet unreleased EFI-only Macs could still be booted by the non-EFI
DTK systems so long as the kernel checked to ensure the boot tables were
filled in appropriately. Modern xnu requires a system table and a runtime
services table and performs no checks whatsoever to ensure the pointers to
these tables are non-NULL. Therefore, any modern xnu kernel will page fault
early on in the boot process if the system table pointer is zero.
Even before that happens, the tsc_init function in modern xnu requires the FSB
Frequency to be a property in the /efi/platform node of the device tree or else
it panics the bootstrap process very early on.
As of this writing, the current implementation found here is good enough
to make the currently available xnu kernel boot without modification on a
system with an appropriate processor. With a minor source modification to
the tsc_init function to remove the explicit check for Core or Core 2
processors the kernel can be made to boot on other processors so long as
the code can be executed by the processor and the machine contains the
necessary hardware.
*/
/*==========================================================================
* Utility function to make a device tree string from an EFI_GUID
*/
static inline char * mallocStringForGuid(EFI_GUID const *pGuid)
{
char *string = malloc(37);
efi_guid_unparse_upper(pGuid, string);
return string;
char *string = malloc(37);
efi_guid_unparse_upper(pGuid, string);
return string;
}
/*==========================================================================
* Function to map 32 bit physical address to 64 bit virtual address
*/
static uint64_t ptov64(uint32_t addr)
{
return ((uint64_t)addr | 0xFFFFFF8000000000ULL);
return ((uint64_t)addr | 0xFFFFFF8000000000ULL);
}
/*==========================================================================
* Fake EFI implementation
*/
static EFI_UINT32 const FIRMWARE_REVISION = 132; /* FIXME: Find a constant for this. */
/* Default platform system_id (fix by IntVar) */
static EFI_CHAR8 const SYSTEM_ID[] = "0123456789ABCDEF";//random value gen by uuidgen
static EFI_CHAR8 const SYSTEM_ID[] = "0123456789ABCDEF"; //random value gen by uuidgen
/* Just a ret instruction */
static uint8_t const VOIDRET_INSTRUCTIONS[] = {0xc3};
/* movl $0x80000003,%eax; ret */
static uint8_t const UNSUPPORTEDRET_INSTRUCTIONS[] = {0xb8, 0x03, 0x00, 0x00, 0x80, 0xc3};
i = gST64->NumberOfTableEntries;
}
/* We only do adds, not modifications and deletes like InstallConfigurationTable */
if(i >= MAX_CONFIGURATION_TABLE_ENTRIES)
stop("Ran out of space for configuration tables. Increase the reserved size in the code.\n");
if(pGuid == NULL)
return EFI_INVALID_PARAMETER;
if(table != NULL)
{
/* FIXME
((EFI_CONFIGURATION_TABLE_64 *)gST->ConfigurationTable)[i].VendorGuid = *pGuid;
((EFI_CONFIGURATION_TABLE_64 *)gST->ConfigurationTable)[i].VendorTable = (EFI_PTR64)table;
++gST->NumberOfTableEntries;
*/
Node *tableNode = DT__AddChild(gEfiConfigurationTableNode, mallocStringForGuid(pGuid));
/* Use the pointer to the GUID we just stuffed into the system table */
DT__AddProperty(tableNode, "guid", sizeof(EFI_GUID), (void*)pGuid);
/* The "table" property is the 32-bit (in our implementation) physical address of the table */
DT__AddProperty(tableNode, "table", sizeof(void*) * 2, table);
/* Assume the alias pointer is a global or static piece of data */
if(alias != NULL)
DT__AddProperty(tableNode, "alias", strlen(alias)+1, (char*)alias);
return EFI_SUCCESS;
}
return EFI_UNSUPPORTED;
// We only do adds, not modifications and deletes like InstallConfigurationTable
if (i >= MAX_CONFIGURATION_TABLE_ENTRIES)
stop("Ran out of space for configuration tables. Increase the reserved size in the code.\n");
if (pGuid == NULL)
return EFI_INVALID_PARAMETER;
if (table != NULL)
{
// FIXME
//((EFI_CONFIGURATION_TABLE_64 *)gST->ConfigurationTable)[i].VendorGuid = *pGuid;
//((EFI_CONFIGURATION_TABLE_64 *)gST->ConfigurationTable)[i].VendorTable = (EFI_PTR64)table;
//++gST->NumberOfTableEntries;
Node *tableNode = DT__AddChild(gEfiConfigurationTableNode, mallocStringForGuid(pGuid));
// Use the pointer to the GUID we just stuffed into the system table
DT__AddProperty(tableNode, "guid", sizeof(EFI_GUID), (void*)pGuid);
// The "table" property is the 32-bit (in our implementation) physical address of the table
DT__AddProperty(tableNode, "table", sizeof(void*) * 2, table);
// Assume the alias pointer is a global or static piece of data
if (alias != NULL)
DT__AddProperty(tableNode, "alias", strlen(alias)+1, (char*)alias);
return EFI_SUCCESS;
}
return EFI_UNSUPPORTED;
}
//Azi: crc32 done in place, on the cases were it wasn't.
}*/
/*
What we do here is simply allocate a fake EFI system table and a fake EFI
runtime services table.
* What we do here is simply allocate a fake EFI system table and a fake EFI
* runtime services table.
*
* Because we build against modern headers with kBootArgsRevision 4 we
* also take care to set efiMode = 32.
*/
Because we build against modern headers with kBootArgsRevision 4 we
also take care to set efiMode = 32.
*/
void setupEfiTables32(void)
{
// We use the fake_efi_pages struct so that we only need to do one kernel
}
/*
In addition to the EFI tables there is also the EFI device tree node.
In particular, we need /efi/platform to have an FSBFrequency key. Without it,
the tsc_init function will panic very early on in kernel startup, before
the console is available.
*/
* In addition to the EFI tables there is also the EFI device tree node.
* In particular, we need /efi/platform to have an FSBFrequency key. Without it,
* the tsc_init function will panic very early on in kernel startup, before
* the console is available.
*/
/*==========================================================================
* FSB Frequency detection
static const char const MODEL_PROP[] = "Model";
/* Get an smbios option string option to convert to EFI_CHAR16 string */
/*
* Get an smbios option string option to convert to EFI_CHAR16 string
*/
static EFI_CHAR16* getSmbiosChar16(const char * key, size_t* len)
{
const char * src= getStringForKey(key, &bootInfo->smbiosConfig);
EFI_CHAR16* dst = 0;
size_t i=0;
const char*src = getStringForKey(key, &bootInfo->smbiosConfig);
EFI_CHAR16* dst = 0;
size_t i = 0;
if (!key || !(*key) || !len || !src) return 0;
*len = strlen(src);
dst = (EFI_CHAR16*) malloc( ((*len)+1) * 2 );
for (; i < (*len); i++) dst[i] = src[i];
dst[(*len)] = '\0';
*len = ((*len)+1)*2; // return the CHAR16 bufsize in cluding zero terminated CHAR16
return dst;
}
if (!key || !(*key) || !len || !src) return 0;
/*
* Get the SystemID from the bios dmi info
*/
*len = strlen(src);
dst = (EFI_CHAR16*) malloc( ((*len)+1) * 2 );
for (; i < (*len); i++) dst[i] = src[i];
dst[(*len)] = '\0';
*len = ((*len)+1)*2; // return the CHAR16 bufsize in cluding zero terminated CHAR16
return dst;
}
/* Get the SystemID from the bios dmi info */
static EFI_CHAR8* getSmbiosUUID()
staticEFI_CHAR8* getSmbiosUUID()
{
static EFI_CHAR8 uuid[UUID_LEN];
int i, isZero, isOnes;
struct SMBEntryPoint*smbios;
SMBByte*p;
inti, isZero, isOnes;
static EFI_CHAR8 uuid[UUID_LEN];
smbios = getSmbios(SMBIOS_PATCHED);/* checks for _SM_ anchor and table header checksum */
SMBByte*p;
smbios = getSmbios(SMBIOS_PATCHED); // checks for _SM_ anchor and table header checksum
if (smbios==NULL) return 0; // getSmbios() return a non null value if smbios is found
p = (SMBByte*) FindFirstDmiTableOfType(1, 0x19); /* Type 1: (3.3.2) System Information */
p = (SMBByte*) FindFirstDmiTableOfType(1, 0x19); // Type 1: (3.3.2) System Information
if (p==NULL) return NULL;
verbose("Found SMBIOS System Information Table 1\n");
p += 8;
for (i=0, isZero=1, isOnes=1; i<UUID_LEN; i++) {
for (i=0, isZero=1, isOnes=1; i<UUID_LEN; i++)
{
if (p[i] != 0x00) isZero = 0;
if (p[i] != 0xff) isOnes = 0;
}
if (isZero || isOnes) {/* empty or setable means: no uuid present */
if (isZero || isOnes) // empty or setable means: no uuid present
{
verbose("No UUID present in SMBIOS System Information Table\n");
return 0;
}
memcpy(uuid, p, UUID_LEN);
return uuid;
}
/* return a binary UUID value from the overriden SystemID and SMUUID if found,
/*
* return a binary UUID value from the overriden SystemID and SMUUID if found,
* or from the bios if not, or from a fixed value if no bios value is found
*/
static EFI_CHAR8* getSystemID()
{ // unable to determine UUID for host. Error: 35 fix
{
// unable to determine UUID for host. Error: 35 fix
// Rek: new SMsystemid option conforming to smbios notation standards, this option should
// belong to smbios config only ...
const char *sysId = getStringForKey(kSystemID, &bootInfo->bootConfig);
EFI_CHAR8* ret = getUUIDFromString(sysId);
// Rek: new SMsystemid option conforming to smbios notation standards, this option should
// belong to smbios config only ...
const char * sysId = getStringForKey(kSystemID, &bootInfo->bootConfig);
EFI_CHAR8* ret = getUUIDFromString(sysId);
if (!sysId || !ret) // try bios dmi info UUID extraction
{
ret = getSmbiosUUID();
sysId = 0;
}
if (!ret) // no bios dmi UUID available, set a fixed value for system-id
ret=getUUIDFromString((sysId = (const char*) SYSTEM_ID));
verbose("Customizing SystemID with : %s\n", getStringFromUUID(ret)); // apply a nice formatting to the displayed output
return ret;
}
if(!sysId || !ret) { // try bios dmi info UUID extraction
ret = getSmbiosUUID();
sysId = 0;
}
if(!ret) // no bios dmi UUID available, set a fixed value for system-id
ret=getUUIDFromString((sysId = (const char*) SYSTEM_ID));
/*
* Must be called AFTER setup Acpi because we need to take care of correct
* facp content to reflect in ioregs
*/
verbose("Customizing SystemID with : %s\n", getStringFromUUID(ret)); // apply a nice formatting to the displayed output
return ret;
}
// must be called AFTER setup Acpi because we need to take care of correct facp content to reflect in ioregs
void setupSystemType()
{
Node *node = DT__FindNode("/", false);
if (node == 0) stop("Couldn't get root node");
// we need to write this property after facp parsing
/* Export system-type only if it has been overrriden by the SystemType option */
DT__AddProperty(node, SYSTEM_TYPE_PROP, sizeof(Platform.Type), &Platform.Type);
Node *node = DT__FindNode("/", false);
if (node == 0) stop("Couldn't get root node");
// we need to write this property after facp parsing
// Export system-type only if it has been overrriden by the SystemType option
DT__AddProperty(node, SYSTEM_TYPE_PROP, sizeof(Platform.Type), &Platform.Type);
}
void setupEfiDeviceTree(void)
{
EFI_CHAR16* ret16=0;
EFI_CHAR8* ret=0;
size_t len=0;
Node *node;
node = DT__FindNode("/", false);
if (node == 0) stop("Couldn't get root node");
/* We could also just do DT__FindNode("/efi/platform", true)
* But I think eventually we want to fill stuff in the efi node
* too so we might as well create it so we have a pointer for it too.
*/
node = DT__AddChild(node, "efi");
EFI_CHAR8* ret = 0;
EFI_CHAR16* ret16 = 0;
size_t len = 0;
Node*node;
node = DT__FindNode("/", false);
if (node == 0) stop("Couldn't get root node");
// We could also just do DT__FindNode("/efi/platform", true)
// But I think eventually we want to fill stuff in the efi node
// too so we might as well create it so we have a pointer for it too.
node = DT__AddChild(node, "efi");
if (archCpuType == CPU_TYPE_I386)
{
DT__AddProperty(node, FIRMWARE_ABI_PROP, sizeof(FIRMWARE_ABI_32_PROP_VALUE), (char*)FIRMWARE_ABI_32_PROP_VALUE);
}
DT__AddProperty(node, FIRMWARE_REVISION_PROP, sizeof(FIRMWARE_REVISION), (EFI_UINT32*)&FIRMWARE_REVISION);
DT__AddProperty(node, FIRMWARE_VENDOR_PROP, sizeof(FIRMWARE_VENDOR), (EFI_CHAR16*)FIRMWARE_VENDOR);
/* TODO: Fill in other efi properties if necessary */
/* Set up the /efi/runtime-services table node similar to the way a child node of configuration-table
* is set up. That is, name and table properties */
Node *runtimeServicesNode = DT__AddChild(node, "runtime-services");
DT__AddProperty(node, FIRMWARE_VENDOR_PROP, sizeof(FIRMWARE_VENDOR), (EFI_CHAR16*)FIRMWARE_VENDOR);
// TODO: Fill in other efi properties if necessary
// Set up the /efi/runtime-services table node similar to the way a child node of configuration-table
// is set up. That is, name and table properties
Node *runtimeServicesNode = DT__AddChild(node, "runtime-services");
if (archCpuType == CPU_TYPE_I386)
{
// The value of the table property is the 32-bit physical address for the RuntimeServices table.
DT__AddProperty(runtimeServicesNode, "table", sizeof(uint64_t), &gST64->RuntimeServices);
}
/* Set up the /efi/configuration-table node which will eventually have several child nodes for
* all of the configuration tables needed by various kernel extensions.
*/
gEfiConfigurationTableNode = DT__AddChild(node, "configuration-table");
// Set up the /efi/configuration-table node which will eventually have several child nodes for
// all of the configuration tables needed by various kernel extensions.
gEfiConfigurationTableNode = DT__AddChild(node, "configuration-table");
// Now fill in the /efi/platform Node
Node *efiPlatformNode = DT__AddChild(node, "platform");
// NOTE WELL: If you do add FSB Frequency detection, make sure to store
// the value in the fsbFrequency global and not an malloc'd pointer
// because the DT_AddProperty function does not copy its args.
if (Platform.CPU.FSBFrequency != 0)
DT__AddProperty(efiPlatformNode, FSB_Frequency_prop, sizeof(uint64_t), &Platform.CPU.FSBFrequency);
// Export TSC and CPU frequencies for use by the kernel or KEXTs
if (Platform.CPU.TSCFrequency != 0)
DT__AddProperty(efiPlatformNode, TSC_Frequency_prop, sizeof(uint64_t), &Platform.CPU.TSCFrequency);
if (Platform.CPU.CPUFrequency != 0)
DT__AddProperty(efiPlatformNode, CPU_Frequency_prop, sizeof(uint64_t), &Platform.CPU.CPUFrequency);
// Export system-id. Can be disabled with SystemId=No in com.apple.Boot.plist
if ((ret=getSystemID()))
DT__AddProperty(efiPlatformNode, SYSTEM_ID_PROP, UUID_LEN, (EFI_UINT32*) ret);
/* Now fill in the /efi/platform Node */
Node *efiPlatformNode = DT__AddChild(node, "platform");
/* NOTE WELL: If you do add FSB Frequency detection, make sure to store
* the value in the fsbFrequency global and not an malloc'd pointer
* because the DT_AddProperty function does not copy its args.
*/
if(Platform.CPU.FSBFrequency != 0)
DT__AddProperty(efiPlatformNode, FSB_Frequency_prop, sizeof(uint64_t), &Platform.CPU.FSBFrequency);
/* Export TSC and CPU frequencies for use by the kernel or KEXTs */
if(Platform.CPU.TSCFrequency != 0)
DT__AddProperty(efiPlatformNode, TSC_Frequency_prop, sizeof(uint64_t), &Platform.CPU.TSCFrequency);
// Export SystemSerialNumber if present
if ((ret16=getSmbiosChar16("SMserial", &len)))
DT__AddProperty(efiPlatformNode, SYSTEM_SERIAL_PROP, len, ret16);
// Export Model if present
if ((ret16=getSmbiosChar16("SMproductname", &len)))
DT__AddProperty(efiPlatformNode, MODEL_PROP, len, ret16);
// Fill /efi/device-properties node.
setupDeviceProperties(node);
}
if(Platform.CPU.CPUFrequency != 0)
DT__AddProperty(efiPlatformNode, CPU_Frequency_prop, sizeof(uint64_t), &Platform.CPU.CPUFrequency);
/*
* Load the smbios.plist override config file if any
*/
/* Export system-id. Can be disabled with system-id=No in com.apple.Boot.plist */
if((ret=getSystemID()))
DT__AddProperty(efiPlatformNode, SYSTEM_ID_PROP, UUID_LEN, (EFI_UINT32*) ret);
/* Export SystemSerialNumber if present */
if ((ret16=getSmbiosChar16("SMserial", &len)))
DT__AddProperty(efiPlatformNode, SYSTEM_SERIAL_PROP, len, ret16);
/* Export Model if present */
if ((ret16=getSmbiosChar16("SMproductname", &len)))
DT__AddProperty(efiPlatformNode, MODEL_PROP, len, ret16);
/* Fill /efi/device-properties node.
*/
setupDeviceProperties(node);
}
/* Load the smbios.plist override config file if any */
static void setupSmbiosConfigFile()
{
const char * value = getStringForKey(kSMBIOS, &bootInfo->bootConfig);
extern void scan_mem();
if (!value) value = "/Extra/smbios.plist";
if (loadConfigFile(value, &bootInfo->smbiosConfig) == -1) {
verbose("No SMBIOS replacement found\n");
const char * value = getStringForKey(kSMBIOS, &bootInfo->bootConfig);
extern void scan_mem();
if (!value) value = "/Extra/smbios.plist";
if (loadConfigFile(value, &bootInfo->smbiosConfig) == -1)
{
verbose("No SMBIOS replacement found\n");
}
// get a chance to scan mem dynamically if user asks for it while having the config options loaded as well
// as opposed to when it was in scan_platform(), also load the orig. smbios so that we can access dmi info without
// patching the smbios yet
getSmbios(SMBIOS_ORIGINAL);
scan_mem();
smbios_p = (EFI_PTR32) getSmbios(SMBIOS_PATCHED);// process smbios asap
smbios_p = (EFI_PTR32) getSmbios(SMBIOS_PATCHED); // process smbios asap
}
/* Installs all the needed configuration table entries */
/*
* Installs all the needed configuration table entries
*/
static void setupEfiConfigurationTable()
{
smbios_p = (EFI_PTR32)getSmbios(SMBIOS_PATCHED);
}
}
/*
* Entrypoint from boot.c
*/
/* Entrypoint from boot.c */
void setupFakeEfi(void)
{
// Generate efi device strings

Archive Download the corresponding diff file

Revision: 301