Chameleon

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

Archive Download this file

Attachment to issue 21

Created: 13 years 9 months ago by Azimutz