Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 28