Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/CleanCut/i386/libsaio/fake_efi.c

1
2/*
3 * Copyright 2007 David F. Elliott. All rights reserved.
4 */
5
6#include "libsaio.h"
7#include "boot.h"
8#include "bootstruct.h"
9#include "efi.h"
10#include "acpi.h"
11#include "fake_efi.h"
12#include "efi_tables.h"
13#include "platform.h"
14#include "acpi_patcher.h"
15#include "smbios_patcher.h"
16#include "device_inject.h"
17#include "convert.h"
18#include "pci.h"
19#include "sl.h"
20
21extern struct SMBEntryPoint * getSmbios(int which); // now cached
22extern void setup_pci_devs(pci_dt_t *pci_dt);
23
24/*
25Modern Darwin kernels require some amount of EFI because Apple machines all
26have EFI. Modifying the kernel source to not require EFI is of course
27possible but would have to be maintained as a separate patch because it is
28unlikely that Apple wishes to add legacy support to their kernel.
29
30As you can see from the Apple-supplied code in bootstruct.c, it seems that
31the intention was clearly to modify this booter to provide EFI-like structures
32to the kernel rather than modifying the kernel to handle non-EFI stuff. This
33makes a lot of sense from an engineering point of view as it means the kernel
34for the as yet unreleased EFI-only Macs could still be booted by the non-EFI
35DTK systems so long as the kernel checked to ensure the boot tables were
36filled in appropriately. Modern xnu requires a system table and a runtime
37services table and performs no checks whatsoever to ensure the pointers to
38these tables are non-NULL. Therefore, any modern xnu kernel will page fault
39early on in the boot process if the system table pointer is zero.
40
41Even before that happens, the tsc_init function in modern xnu requires the FSB
42Frequency to be a property in the /efi/platform node of the device tree or else
43it panics the bootstrap process very early on.
44
45As of this writing, the current implementation found here is good enough
46to make the currently available xnu kernel boot without modification on a
47system with an appropriate processor. With a minor source modification to
48the tsc_init function to remove the explicit check for Core or Core 2
49processors the kernel can be made to boot on other processors so long as
50the code can be executed by the processor and the machine contains the
51necessary hardware.
52*/
53
54
55/*==========================================================================
56 * Utility function to make a device tree string from an EFI_GUID
57 */
58
59static inline char * mallocStringForGuid(EFI_GUID const *pGuid)
60{
61 char *string = malloc(37);
62 efi_guid_unparse_upper(pGuid, string);
63 return string;
64}
65
66
67/*==========================================================================
68 * Function to map 32 bit physical address to 64 bit virtual address
69 */
70static uint64_t ptov64(uint32_t addr)
71{
72 return ((uint64_t)addr | 0xFFFFFF8000000000ULL);
73}
74
75
76/*==========================================================================
77 * Fake EFI implementation
78 */
79
80/* Identify ourselves as the EFI firmware vendor */
81static EFI_CHAR16 const FIRMWARE_VENDOR[] = {'C','h','a','m','e','l','e','o','n','_','2','.','0', 0};
82static EFI_UINT32 const FIRMWARE_REVISION = 132; /* FIXME: Find a constant for this. */
83
84/* Default platform system_id (fix by IntVar) */
85static EFI_CHAR8 const SYSTEM_ID[] = "0123456789ABCDEF";//random value gen by uuidgen
86
87/* Just a ret instruction */
88static uint8_t const VOIDRET_INSTRUCTIONS[] = {0xc3};
89/* movl $0x80000003,%eax; ret */
90static uint8_t const UNSUPPORTEDRET_INSTRUCTIONS[] = {0xb8, 0x03, 0x00, 0x00, 0x80, 0xc3};
91
92EFI_SYSTEM_TABLE_32 *gST32 = NULL;
93EFI_SYSTEM_TABLE_64 *gST64 = NULL;
94Node *gEfiConfigurationTableNode = NULL;
95
96extern EFI_STATUS addConfigurationTable(EFI_GUID const *pGuid, void *table, char const *alias)
97{
98 EFI_UINTN i = 0;
99
100//Azi: as is, cpu's with em64t will use EFI64 on pre 10.6 systems,
101// wich seems to cause no problem. In case it does, force i386 arch.
102if (archCpuType == CPU_TYPE_I386)
103{
104i = gST32->NumberOfTableEntries;
105}
106else
107{
108i = gST64->NumberOfTableEntries;
109}
110
111 /* We only do adds, not modifications and deletes like InstallConfigurationTable */
112 if(i >= MAX_CONFIGURATION_TABLE_ENTRIES)
113 stop("Ran out of space for configuration tables. Increase the reserved size in the code.\n");
114
115 if(pGuid == NULL)
116 return EFI_INVALID_PARAMETER;
117
118 if(table != NULL)
119 {
120 /* FIXME
121 ((EFI_CONFIGURATION_TABLE_64 *)gST->ConfigurationTable)[i].VendorGuid = *pGuid;
122 ((EFI_CONFIGURATION_TABLE_64 *)gST->ConfigurationTable)[i].VendorTable = (EFI_PTR64)table;
123
124 ++gST->NumberOfTableEntries;
125 */
126 Node *tableNode = DT__AddChild(gEfiConfigurationTableNode, mallocStringForGuid(pGuid));
127
128 /* Use the pointer to the GUID we just stuffed into the system table */
129 DT__AddProperty(tableNode, "guid", sizeof(EFI_GUID), (void*)pGuid);
130
131 /* The "table" property is the 32-bit (in our implementation) physical address of the table */
132 DT__AddProperty(tableNode, "table", sizeof(void*) * 2, table);
133
134 /* Assume the alias pointer is a global or static piece of data */
135 if(alias != NULL)
136 DT__AddProperty(tableNode, "alias", strlen(alias)+1, (char*)alias);
137
138 return EFI_SUCCESS;
139 }
140 return EFI_UNSUPPORTED;
141}
142
143//Azi: crc32 done in place, on the cases were it wasn't.
144/*static inline void fixupEfiSystemTableCRC32(EFI_SYSTEM_TABLE_64 *efiSystemTable)
145{
146 efiSystemTable->Hdr.CRC32 = 0;
147 efiSystemTable->Hdr.CRC32 = crc32(0L, efiSystemTable, efiSystemTable->Hdr.HeaderSize);
148}*/
149
150/*
151What we do here is simply allocate a fake EFI system table and a fake EFI
152runtime services table.
153
154Because we build against modern headers with kBootArgsRevision 4 we
155also take care to set efiMode = 32.
156*/
157void setupEfiTables32(void)
158{
159// We use the fake_efi_pages struct so that we only need to do one kernel
160// memory allocation for all needed EFI data. Otherwise, small allocations
161// like the FIRMWARE_VENDOR string would take up an entire page.
162// NOTE WELL: Do NOT assume this struct has any particular layout within itself.
163// It is absolutely not intended to be publicly exposed anywhere
164// We say pages (plural) although right now we are well within the 1 page size
165// and probably will stay that way.
166struct fake_efi_pages
167{
168EFI_SYSTEM_TABLE_32 efiSystemTable;
169EFI_RUNTIME_SERVICES_32 efiRuntimeServices;
170EFI_CONFIGURATION_TABLE_32 efiConfigurationTable[MAX_CONFIGURATION_TABLE_ENTRIES];
171EFI_CHAR16 firmwareVendor[sizeof(FIRMWARE_VENDOR)/sizeof(EFI_CHAR16)];
172uint8_t voidret_instructions[sizeof(VOIDRET_INSTRUCTIONS)/sizeof(uint8_t)];
173uint8_t unsupportedret_instructions[sizeof(UNSUPPORTEDRET_INSTRUCTIONS)/sizeof(uint8_t)];
174};
175
176struct fake_efi_pages *fakeEfiPages = (struct fake_efi_pages*)AllocateKernelMemory(sizeof(struct fake_efi_pages));
177
178// Zero out all the tables in case fields are added later
179bzero(fakeEfiPages, sizeof(struct fake_efi_pages));
180
181// --------------------------------------------------------------------
182// Initialize some machine code that will return EFI_UNSUPPORTED for
183// functions returning int and simply return for void functions.
184memcpy(fakeEfiPages->voidret_instructions, VOIDRET_INSTRUCTIONS, sizeof(VOIDRET_INSTRUCTIONS));
185memcpy(fakeEfiPages->unsupportedret_instructions, UNSUPPORTEDRET_INSTRUCTIONS, sizeof(UNSUPPORTEDRET_INSTRUCTIONS));
186
187// --------------------------------------------------------------------
188// System table
189EFI_SYSTEM_TABLE_32 *efiSystemTable = gST32 = &fakeEfiPages->efiSystemTable;
190efiSystemTable->Hdr.Signature = EFI_SYSTEM_TABLE_SIGNATURE;
191efiSystemTable->Hdr.Revision = EFI_SYSTEM_TABLE_REVISION;
192efiSystemTable->Hdr.HeaderSize = sizeof(EFI_SYSTEM_TABLE_32);
193efiSystemTable->Hdr.CRC32 = 0; // Initialize to zero and then do CRC32
194efiSystemTable->Hdr.Reserved = 0;
195
196efiSystemTable->FirmwareVendor = (EFI_PTR32)&fakeEfiPages->firmwareVendor;
197memcpy(fakeEfiPages->firmwareVendor, FIRMWARE_VENDOR, sizeof(FIRMWARE_VENDOR));
198efiSystemTable->FirmwareRevision = FIRMWARE_REVISION;
199
200// XXX: We may need to have basic implementations of ConIn/ConOut/StdErr
201// The EFI spec states that all handles are invalid after boot services have been
202// exited so we can probably get by with leaving the handles as zero.
203efiSystemTable->ConsoleInHandle = 0;
204efiSystemTable->ConIn = 0;
205
206efiSystemTable->ConsoleOutHandle = 0;
207efiSystemTable->ConOut = 0;
208
209efiSystemTable->StandardErrorHandle = 0;
210efiSystemTable->StdErr = 0;
211
212efiSystemTable->RuntimeServices = (EFI_PTR32)&fakeEfiPages->efiRuntimeServices;
213
214// According to the EFI spec, BootServices aren't valid after the
215// boot process is exited so we can probably do without it.
216// Apple didn't provide a definition for it in pexpert/i386/efi.h
217// so I'm guessing they don't use it.
218efiSystemTable->BootServices = 0;
219
220efiSystemTable->NumberOfTableEntries = 0;
221efiSystemTable->ConfigurationTable = (EFI_PTR32)fakeEfiPages->efiConfigurationTable;
222
223// We're done. Now CRC32 the thing so the kernel will accept it.
224// Must be initialized to zero before CRC32, done above.
225gST32->Hdr.CRC32 = crc32(0L, gST32, gST32->Hdr.HeaderSize);
226
227// --------------------------------------------------------------------
228// Runtime services
229EFI_RUNTIME_SERVICES_32 *efiRuntimeServices = &fakeEfiPages->efiRuntimeServices;
230efiRuntimeServices->Hdr.Signature = EFI_RUNTIME_SERVICES_SIGNATURE;
231efiRuntimeServices->Hdr.Revision = EFI_RUNTIME_SERVICES_REVISION;
232efiRuntimeServices->Hdr.HeaderSize = sizeof(EFI_RUNTIME_SERVICES_32);
233efiRuntimeServices->Hdr.CRC32 = 0;
234efiRuntimeServices->Hdr.Reserved = 0;
235
236// There are a number of function pointers in the efiRuntimeServices table.
237// These are the Foundation (e.g. core) services and are expected to be present on
238// all EFI-compliant machines.Some kernel extensions (notably AppleEFIRuntime)
239// will call these without checking to see if they are null.
240//
241// We don't really feel like doing an EFI implementation in the bootloader
242// but it is nice if we can at least prevent a complete crash by
243// at least providing some sort of implementation until one can be provided
244// nicely in a kext.
245void (*voidret_fp)() = (void*)fakeEfiPages->voidret_instructions;
246void (*unsupportedret_fp)() = (void*)fakeEfiPages->unsupportedret_instructions;
247efiRuntimeServices->GetTime = (EFI_PTR32)unsupportedret_fp;
248efiRuntimeServices->SetTime = (EFI_PTR32)unsupportedret_fp;
249efiRuntimeServices->GetWakeupTime = (EFI_PTR32)unsupportedret_fp;
250efiRuntimeServices->SetWakeupTime = (EFI_PTR32)unsupportedret_fp;
251efiRuntimeServices->SetVirtualAddressMap = (EFI_PTR32)unsupportedret_fp;
252efiRuntimeServices->ConvertPointer = (EFI_PTR32)unsupportedret_fp;
253efiRuntimeServices->GetVariable = (EFI_PTR32)unsupportedret_fp;
254efiRuntimeServices->GetNextVariableName = (EFI_PTR32)unsupportedret_fp;
255efiRuntimeServices->SetVariable = (EFI_PTR32)unsupportedret_fp;
256efiRuntimeServices->GetNextHighMonotonicCount = (EFI_PTR32)unsupportedret_fp;
257efiRuntimeServices->ResetSystem = (EFI_PTR32)voidret_fp;
258
259// We're done.Now CRC32 the thing so the kernel will accept it
260efiRuntimeServices->Hdr.CRC32 = crc32(0L, efiRuntimeServices, efiRuntimeServices->Hdr.HeaderSize);
261
262// --------------------------------------------------------------------
263// Finish filling in the rest of the boot args that we need.
264bootArgs->efiSystemTable = (uint32_t)efiSystemTable;
265bootArgs->efiMode = kBootArgsEfiMode32;
266
267// The bootArgs structure as a whole is bzero'd so we don't need to fill in
268// things like efiRuntimeServices* and what not.
269//
270// In fact, the only code that seems to use that is the hibernate code so it
271// knows not to save the pages. It even checks to make sure its nonzero.
272}
273
274void setupEfiTables64(void)
275{
276struct fake_efi_pages
277{
278EFI_SYSTEM_TABLE_64 efiSystemTable;
279EFI_RUNTIME_SERVICES_64 efiRuntimeServices;
280EFI_CONFIGURATION_TABLE_64 efiConfigurationTable[MAX_CONFIGURATION_TABLE_ENTRIES];
281EFI_CHAR16 firmwareVendor[sizeof(FIRMWARE_VENDOR)/sizeof(EFI_CHAR16)];
282uint8_t voidret_instructions[sizeof(VOIDRET_INSTRUCTIONS)/sizeof(uint8_t)];
283uint8_t unsupportedret_instructions[sizeof(UNSUPPORTEDRET_INSTRUCTIONS)/sizeof(uint8_t)];
284};
285
286struct fake_efi_pages *fakeEfiPages = (struct fake_efi_pages*)AllocateKernelMemory(sizeof(struct fake_efi_pages));
287
288// Zero out all the tables in case fields are added later
289bzero(fakeEfiPages, sizeof(struct fake_efi_pages));
290
291// --------------------------------------------------------------------
292// Initialize some machine code that will return EFI_UNSUPPORTED for
293// functions returning int and simply return for void functions.
294memcpy(fakeEfiPages->voidret_instructions, VOIDRET_INSTRUCTIONS, sizeof(VOIDRET_INSTRUCTIONS));
295memcpy(fakeEfiPages->unsupportedret_instructions, UNSUPPORTEDRET_INSTRUCTIONS, sizeof(UNSUPPORTEDRET_INSTRUCTIONS));
296
297// --------------------------------------------------------------------
298// System table
299EFI_SYSTEM_TABLE_64 *efiSystemTable = gST64 = &fakeEfiPages->efiSystemTable;
300efiSystemTable->Hdr.Signature = EFI_SYSTEM_TABLE_SIGNATURE;
301efiSystemTable->Hdr.Revision = EFI_SYSTEM_TABLE_REVISION;
302efiSystemTable->Hdr.HeaderSize = sizeof(EFI_SYSTEM_TABLE_64);
303efiSystemTable->Hdr.CRC32 = 0; // Initialize to zero and then do CRC32
304efiSystemTable->Hdr.Reserved = 0;
305
306efiSystemTable->FirmwareVendor = ptov64((EFI_PTR32)&fakeEfiPages->firmwareVendor);
307memcpy(fakeEfiPages->firmwareVendor, FIRMWARE_VENDOR, sizeof(FIRMWARE_VENDOR));
308efiSystemTable->FirmwareRevision = FIRMWARE_REVISION;
309
310// XXX: We may need to have basic implementations of ConIn/ConOut/StdErr
311// The EFI spec states that all handles are invalid after boot services have been
312// exited so we can probably get by with leaving the handles as zero.
313efiSystemTable->ConsoleInHandle = 0;
314efiSystemTable->ConIn = 0;
315
316efiSystemTable->ConsoleOutHandle = 0;
317efiSystemTable->ConOut = 0;
318
319efiSystemTable->StandardErrorHandle = 0;
320efiSystemTable->StdErr = 0;
321
322efiSystemTable->RuntimeServices = ptov64((EFI_PTR32)&fakeEfiPages->efiRuntimeServices);
323// According to the EFI spec, BootServices aren't valid after the
324// boot process is exited so we can probably do without it.
325// Apple didn't provide a definition for it in pexpert/i386/efi.h
326// so I'm guessing they don't use it.
327efiSystemTable->BootServices = 0;
328
329efiSystemTable->NumberOfTableEntries = 0;
330efiSystemTable->ConfigurationTable = ptov64((EFI_PTR32)fakeEfiPages->efiConfigurationTable);
331
332// We're done.Now CRC32 the thing so the kernel will accept it
333gST64->Hdr.CRC32 = crc32(0L, gST64, gST64->Hdr.HeaderSize);
334
335// --------------------------------------------------------------------
336// Runtime services
337EFI_RUNTIME_SERVICES_64 *efiRuntimeServices = &fakeEfiPages->efiRuntimeServices;
338efiRuntimeServices->Hdr.Signature = EFI_RUNTIME_SERVICES_SIGNATURE;
339efiRuntimeServices->Hdr.Revision = EFI_RUNTIME_SERVICES_REVISION;
340efiRuntimeServices->Hdr.HeaderSize = sizeof(EFI_RUNTIME_SERVICES_64);
341efiRuntimeServices->Hdr.CRC32 = 0;
342efiRuntimeServices->Hdr.Reserved = 0;
343
344// There are a number of function pointers in the efiRuntimeServices table.
345// These are the Foundation (e.g. core) services and are expected to be present on
346// all EFI-compliant machines.Some kernel extensions (notably AppleEFIRuntime)
347// will call these without checking to see if they are null.
348//
349// We don't really feel like doing an EFI implementation in the bootloader
350// but it is nice if we can at least prevent a complete crash by
351// at least providing some sort of implementation until one can be provided
352// nicely in a kext.
353
354void (*voidret_fp)() = (void*)fakeEfiPages->voidret_instructions;
355void (*unsupportedret_fp)() = (void*)fakeEfiPages->unsupportedret_instructions;
356efiRuntimeServices->GetTime = ptov64((EFI_PTR32)unsupportedret_fp);
357efiRuntimeServices->SetTime = ptov64((EFI_PTR32)unsupportedret_fp);
358efiRuntimeServices->GetWakeupTime = ptov64((EFI_PTR32)unsupportedret_fp);
359efiRuntimeServices->SetWakeupTime = ptov64((EFI_PTR32)unsupportedret_fp);
360efiRuntimeServices->SetVirtualAddressMap = ptov64((EFI_PTR32)unsupportedret_fp);
361efiRuntimeServices->ConvertPointer = ptov64((EFI_PTR32)unsupportedret_fp);
362efiRuntimeServices->GetVariable = ptov64((EFI_PTR32)unsupportedret_fp);
363efiRuntimeServices->GetNextVariableName = ptov64((EFI_PTR32)unsupportedret_fp);
364efiRuntimeServices->SetVariable = ptov64((EFI_PTR32)unsupportedret_fp);
365efiRuntimeServices->GetNextHighMonotonicCount = ptov64((EFI_PTR32)unsupportedret_fp);
366efiRuntimeServices->ResetSystem = ptov64((EFI_PTR32)voidret_fp);
367
368// We're done.Now CRC32 the thing so the kernel will accept it
369efiRuntimeServices->Hdr.CRC32 = crc32(0L, efiRuntimeServices, efiRuntimeServices->Hdr.HeaderSize);
370
371// --------------------------------------------------------------------
372// Finish filling in the rest of the boot args that we need.
373bootArgs->efiSystemTable = (uint32_t)efiSystemTable;
374bootArgs->efiMode = kBootArgsEfiMode64;
375
376// The bootArgs structure as a whole is bzero'd so we don't need to fill in
377// things like efiRuntimeServices* and what not.
378//
379// In fact, the only code that seems to use that is the hibernate code so it
380// knows not to save the pages. It even checks to make sure its nonzero.
381}
382
383/*
384In addition to the EFI tables there is also the EFI device tree node.
385In particular, we need /efi/platform to have an FSBFrequency key. Without it,
386the tsc_init function will panic very early on in kernel startup, before
387the console is available.
388*/
389
390/*==========================================================================
391 * FSB Frequency detection
392 */
393
394/* These should be const but DT__AddProperty takes char* */
395static const char const TSC_Frequency_prop[] = "TSCFrequency";
396static const char const FSB_Frequency_prop[] = "FSBFrequency";
397static const char const CPU_Frequency_prop[] = "CPUFrequency";
398
399/*==========================================================================
400 * SMBIOS
401 */
402
403/* From Foundation/Efi/Guid/Smbios/SmBios.c */
404EFI_GUID const gEfiSmbiosTableGuid = EFI_SMBIOS_TABLE_GUID;
405
406#define SMBIOS_RANGE_START 0x000F0000
407#define SMBIOS_RANGE_END 0x000FFFFF
408
409/* '_SM_' in little endian: */
410#define SMBIOS_ANCHOR_UINT32_LE 0x5f4d535f
411
412#define EFI_ACPI_TABLE_GUID \
413 { \
414 0xeb9d2d30, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
415 }
416
417#define EFI_ACPI_20_TABLE_GUID \
418 { \
419 0x8868e871, 0xe4f1, 0x11d3, { 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \
420 }
421
422EFI_GUID gEfiAcpiTableGuid = EFI_ACPI_TABLE_GUID;
423EFI_GUID gEfiAcpi20TableGuid = EFI_ACPI_20_TABLE_GUID;
424
425
426/*==========================================================================
427 * Fake EFI implementation
428 */
429
430/* These should be const but DT__AddProperty takes char* */
431static const char const FIRMWARE_REVISION_PROP[] = "firmware-revision";
432static const char const FIRMWARE_ABI_PROP[] = "firmware-abi";
433static const char const FIRMWARE_VENDOR_PROP[] = "firmware-vendor";
434static const char const FIRMWARE_ABI_32_PROP_VALUE[] = "EFI32";
435static const char const FIRMWARE_ABI_64_PROP_VALUE[] = "EFI64";
436static const char const SYSTEM_ID_PROP[] = "system-id";
437static const char const SYSTEM_SERIAL_PROP[] = "SystemSerialNumber";
438static const char const SYSTEM_TYPE_PROP[] = "system-type";
439static const char const MODEL_PROP[] = "Model";
440
441
442/* Get an smbios option string option to convert to EFI_CHAR16 string */
443static EFI_CHAR16* getSmbiosChar16(const char * key, size_t* len)
444{
445 const char * src= getStringForKey(key, &bootInfo->smbiosConfig);
446 EFI_CHAR16* dst = 0;
447 size_t i=0;
448
449 if (!key || !(*key) || !len || !src) return 0;
450
451 *len = strlen(src);
452 dst = (EFI_CHAR16*) malloc( ((*len)+1) * 2 );
453 for (; i < (*len); i++) dst[i] = src[i];
454 dst[(*len)] = '\0';
455 *len = ((*len)+1)*2; // return the CHAR16 bufsize in cluding zero terminated CHAR16
456 return dst;
457}
458
459/* Get the SystemID from the bios dmi info */
460static EFI_CHAR8* getSmbiosUUID()
461{
462struct SMBEntryPoint*smbios;
463SMBByte*p;
464inti, isZero, isOnes;
465static EFI_CHAR8 uuid[UUID_LEN];
466
467smbios = getSmbios(SMBIOS_PATCHED);/* checks for _SM_ anchor and table header checksum */
468if (smbios==NULL) return 0; // getSmbios() return a non null value if smbios is found
469
470p = (SMBByte*) FindFirstDmiTableOfType(1, 0x19); /* Type 1: (3.3.2) System Information */
471if (p==NULL) return NULL;
472
473verbose("Found SMBIOS System Information Table 1\n");
474p += 8;
475
476for (i=0, isZero=1, isOnes=1; i<UUID_LEN; i++) {
477if (p[i] != 0x00) isZero = 0;
478if (p[i] != 0xff) isOnes = 0;
479}
480if (isZero || isOnes) {/* empty or setable means: no uuid present */
481verbose("No UUID present in SMBIOS System Information Table\n");
482return 0;
483}
484
485memcpy(uuid, p, UUID_LEN);
486return uuid;
487}
488
489/* return a binary UUID value from the overriden SystemID and SMUUID if found,
490 * or from the bios if not, or from a fixed value if no bios value is found
491 */
492static EFI_CHAR8* getSystemID()
493{ // unable to determine UUID for host. Error: 35 fix
494
495 // Rek: new SMsystemid option conforming to smbios notation standards, this option should
496 // belong to smbios config only ...
497 const char * sysId = getStringForKey(kSystemID, &bootInfo->bootConfig);
498 EFI_CHAR8* ret = getUUIDFromString(sysId);
499
500 if(!sysId || !ret) { // try bios dmi info UUID extraction
501 ret = getSmbiosUUID();
502 sysId = 0;
503 }
504 if(!ret) // no bios dmi UUID available, set a fixed value for system-id
505 ret=getUUIDFromString((sysId = (const char*) SYSTEM_ID));
506
507 verbose("Customizing SystemID with : %s\n", getStringFromUUID(ret)); // apply a nice formatting to the displayed output
508 return ret;
509}
510
511// must be called AFTER setup Acpi because we need to take care of correct facp content to reflect in ioregs
512void setupSystemType()
513{
514 Node *node = DT__FindNode("/", false);
515 if (node == 0) stop("Couldn't get root node");
516 // we need to write this property after facp parsing
517 /* Export system-type only if it has been overrriden by the SystemType option */
518 DT__AddProperty(node, SYSTEM_TYPE_PROP, sizeof(Platform.Type), &Platform.Type);
519}
520
521void setupEfiDeviceTree(void)
522{
523 EFI_CHAR16* ret16=0;
524 EFI_CHAR8* ret=0;
525 size_t len=0;
526 Node *node;
527
528 node = DT__FindNode("/", false);
529
530 if (node == 0) stop("Couldn't get root node");
531
532 /* We could also just do DT__FindNode("/efi/platform", true)
533 * But I think eventually we want to fill stuff in the efi node
534 * too so we might as well create it so we have a pointer for it too.
535 */
536 node = DT__AddChild(node, "efi");
537
538if (archCpuType == CPU_TYPE_I386)
539{
540DT__AddProperty(node, FIRMWARE_ABI_PROP, sizeof(FIRMWARE_ABI_32_PROP_VALUE), (char*)FIRMWARE_ABI_32_PROP_VALUE);
541}
542else
543{
544DT__AddProperty(node, FIRMWARE_ABI_PROP, sizeof(FIRMWARE_ABI_64_PROP_VALUE), (char*)FIRMWARE_ABI_64_PROP_VALUE);
545}
546
547 DT__AddProperty(node, FIRMWARE_REVISION_PROP, sizeof(FIRMWARE_REVISION), (EFI_UINT32*)&FIRMWARE_REVISION);
548 DT__AddProperty(node, FIRMWARE_VENDOR_PROP, sizeof(FIRMWARE_VENDOR), (EFI_CHAR16*)FIRMWARE_VENDOR);
549
550 /* TODO: Fill in other efi properties if necessary */
551
552 /* Set up the /efi/runtime-services table node similar to the way a child node of configuration-table
553 * is set up. That is, name and table properties */
554 Node *runtimeServicesNode = DT__AddChild(node, "runtime-services");
555
556 if (archCpuType == CPU_TYPE_I386)
557{
558// The value of the table property is the 32-bit physical address for the RuntimeServices table.
559// Since the EFI system table already has a pointer to it, we simply use the address of that pointer
560// for the pointer to the property data. Warning.. DT finalization calls free on that but we're not
561// the only thing to use a non-malloc'd pointer for something in the DT
562
563DT__AddProperty(runtimeServicesNode, "table", sizeof(uint64_t), &gST32->RuntimeServices);
564}
565else
566{
567DT__AddProperty(runtimeServicesNode, "table", sizeof(uint64_t), &gST64->RuntimeServices);
568}
569
570 /* Set up the /efi/configuration-table node which will eventually have several child nodes for
571 * all of the configuration tables needed by various kernel extensions.
572 */
573 gEfiConfigurationTableNode = DT__AddChild(node, "configuration-table");
574
575 /* Now fill in the /efi/platform Node */
576 Node *efiPlatformNode = DT__AddChild(node, "platform");
577
578 /* NOTE WELL: If you do add FSB Frequency detection, make sure to store
579 * the value in the fsbFrequency global and not an malloc'd pointer
580 * because the DT_AddProperty function does not copy its args.
581 */
582 if(Platform.CPU.FSBFrequency != 0)
583 DT__AddProperty(efiPlatformNode, FSB_Frequency_prop, sizeof(uint64_t), &Platform.CPU.FSBFrequency);
584
585 /* Export TSC and CPU frequencies for use by the kernel or KEXTs */
586 if(Platform.CPU.TSCFrequency != 0)
587 DT__AddProperty(efiPlatformNode, TSC_Frequency_prop, sizeof(uint64_t), &Platform.CPU.TSCFrequency);
588
589 if(Platform.CPU.CPUFrequency != 0)
590 DT__AddProperty(efiPlatformNode, CPU_Frequency_prop, sizeof(uint64_t), &Platform.CPU.CPUFrequency);
591
592 /* Export system-id. Can be disabled with system-id=No in com.apple.Boot.plist */
593 if((ret=getSystemID()))
594 DT__AddProperty(efiPlatformNode, SYSTEM_ID_PROP, UUID_LEN, (EFI_UINT32*) ret);
595
596 /* Export SystemSerialNumber if present */
597 if ((ret16=getSmbiosChar16("SMserial", &len)))
598 DT__AddProperty(efiPlatformNode, SYSTEM_SERIAL_PROP, len, ret16);
599
600 /* Export Model if present */
601 if ((ret16=getSmbiosChar16("SMproductname", &len)))
602 DT__AddProperty(efiPlatformNode, MODEL_PROP, len, ret16);
603
604 /* Fill /efi/device-properties node.
605 */
606 setupDeviceProperties(node);
607}
608
609/* Load the smbios.plist override config file if any */
610static void setupSmbiosConfigFile()
611{
612 const char * value = getStringForKey(kSMBIOS, &bootInfo->bootConfig);
613 extern void scan_mem();
614
615 if (!value) value = "/Extra/smbios.plist";
616 if (loadConfigFile(value, &bootInfo->smbiosConfig) == -1) {
617 verbose("No SMBIOS replacement found\n");
618 }
619
620 // get a chance to scan mem dynamically if user asks for it while having the config options loaded as well
621 // as opposed to when it was in scan_platform(), also load the orig. smbios so that we can access dmi info without
622 // patching the smbios yet
623 getSmbios(SMBIOS_ORIGINAL);
624 scan_mem();
625 smbios_p = (EFI_PTR32) getSmbios(SMBIOS_PATCHED);// process smbios asap
626}
627
628/* Installs all the needed configuration table entries */
629static void setupEfiConfigurationTable()
630{
631smbios_p = (EFI_PTR32)getSmbios(SMBIOS_PATCHED);
632addConfigurationTable(&gEfiSmbiosTableGuid, &smbios_p, "SMBIOS_P"); //Azi: give an "alias" to this stuff?
633
634// Setup ACPI with DSDT overrides (mackerintel's patch)
635setupAcpi();
636
637// We've obviously changed the count.. so fix up the CRC32
638 if (archCpuType == CPU_TYPE_I386)
639{
640gST32->Hdr.CRC32 = 0;
641gST32->Hdr.CRC32 = crc32(0L, gST32, gST32->Hdr.HeaderSize);
642}
643else
644{
645gST64->Hdr.CRC32 = 0;
646gST64->Hdr.CRC32 = crc32(0L, gST64, gST64->Hdr.HeaderSize);
647}
648}
649
650
651/* Entrypoint from boot.c */
652void setupFakeEfi(void)
653{
654// Generate efi device strings
655setup_pci_devs(root_pci_dev);
656
657// load smbios.plist file if any
658setupSmbiosConfigFile();
659
660// Initialize the base table
661if (archCpuType == CPU_TYPE_I386)
662{
663setupEfiTables32();
664}
665else
666{
667setupEfiTables64();
668}
669
670// Initialize the device tree
671setupEfiDeviceTree();
672
673// Add configuration table entries to both the services table and the device tree
674setupEfiConfigurationTable();
675}
676
677

Archive Download this file

Revision: 299