Chameleon Applications

Chameleon Applications Svn Source Tree

Root/branches/iFabio/i386/libsaio/fake_efi.c

Source at commit 214 created 13 years 5 months ago.
By ifabio, update to chameleon trunk 630, and now the pakage folder is the same as blackosx branch, also add Icon "building" into buildpkg script, and add mint theme info into the English localizable.strings.
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/*
25 * Modern Darwin kernels require some amount of EFI because Apple machines all
26 * have EFI. Modifying the kernel source to not require EFI is of course
27 * possible but would have to be maintained as a separate patch because it is
28 * unlikely that Apple wishes to add legacy support to their kernel.
29 *
30 * As you can see from the Apple-supplied code in bootstruct.c, it seems that
31 * the intention was clearly to modify this booter to provide EFI-like structures
32 * to the kernel rather than modifying the kernel to handle non-EFI stuff. This
33 * makes a lot of sense from an engineering point of view as it means the kernel
34 * for the as yet unreleased EFI-only Macs could still be booted by the non-EFI
35 * DTK systems so long as the kernel checked to ensure the boot tables were
36 * filled in appropriately. Modern xnu requires a system table and a runtime
37 * services table and performs no checks whatsoever to ensure the pointers to
38 * these tables are non-NULL.Therefore, any modern xnu kernel will page fault
39 * early on in the boot process if the system table pointer is zero.
40 *
41 * Even before that happens, the tsc_init function in modern xnu requires the FSB
42 * Frequency to be a property in the /efi/platform node of the device tree or else
43 * it panics the bootstrap process very early on.
44 *
45 * As of this writing, the current implementation found here is good enough
46 * to make the currently available xnu kernel boot without modification on a
47 * system with an appropriate processor. With a minor source modification to
48 * the tsc_init function to remove the explicit check for Core or Core 2
49 * processors the kernel can be made to boot on other processors so long as
50 * the code can be executed by the processor and the machine contains the
51 * necessary hardware.
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{
60char *string = malloc(37);
61efi_guid_unparse_upper(pGuid, string);
62return string;
63}
64
65/*==========================================================================
66 * Function to map 32 bit physical address to 64 bit virtual address
67 */
68
69static uint64_t ptov64(uint32_t addr)
70{
71return ((uint64_t)addr | 0xFFFFFF8000000000ULL);
72}
73
74/*==========================================================================
75 * Fake EFI implementation
76 */
77
78/* Identify ourselves as the EFI firmware vendor */
79static EFI_CHAR16 const FIRMWARE_VENDOR[] = {'C','h','a','m','e','l','e','o','n','_','2','.','0', 0};
80static EFI_UINT32 const FIRMWARE_REVISION = 132; /* FIXME: Find a constant for this. */
81
82/* Default platform system_id (fix by IntVar) */
83static EFI_CHAR8 const SYSTEM_ID[] = "0123456789ABCDEF"; //random value gen by uuidgen
84
85/* Just a ret instruction */
86static uint8_t const VOIDRET_INSTRUCTIONS[] = {0xc3};
87
88/* movl $0x80000003,%eax; ret */
89static uint8_t const UNSUPPORTEDRET_INSTRUCTIONS[] = {0xb8, 0x03, 0x00, 0x00, 0x80, 0xc3};
90
91EFI_SYSTEM_TABLE_32 *gST32 = NULL;
92EFI_SYSTEM_TABLE_64 *gST64 = NULL;
93Node *gEfiConfigurationTableNode = NULL;
94
95extern EFI_STATUS addConfigurationTable(EFI_GUID const *pGuid, void *table, char const *alias)
96{
97EFI_UINTN i = 0;
98
99//Azi: as is, cpu's with em64t will use EFI64 on pre 10.6 systems,
100// wich seems to cause no problem. In case it does, force i386 arch.
101if (archCpuType == CPU_TYPE_I386)
102{
103i = gST32->NumberOfTableEntries;
104}
105else
106{
107i = gST64->NumberOfTableEntries;
108}
109
110// We only do adds, not modifications and deletes like InstallConfigurationTable
111if (i >= MAX_CONFIGURATION_TABLE_ENTRIES)
112stop("Ran out of space for configuration tables. Increase the reserved size in the code.\n");
113
114if (pGuid == NULL)
115return EFI_INVALID_PARAMETER;
116
117if (table != NULL)
118{
119// FIXME
120//((EFI_CONFIGURATION_TABLE_64 *)gST->ConfigurationTable)[i].VendorGuid = *pGuid;
121//((EFI_CONFIGURATION_TABLE_64 *)gST->ConfigurationTable)[i].VendorTable = (EFI_PTR64)table;
122
123//++gST->NumberOfTableEntries;
124
125Node *tableNode = DT__AddChild(gEfiConfigurationTableNode, mallocStringForGuid(pGuid));
126
127// Use the pointer to the GUID we just stuffed into the system table
128DT__AddProperty(tableNode, "guid", sizeof(EFI_GUID), (void*)pGuid);
129
130// The "table" property is the 32-bit (in our implementation) physical address of the table
131DT__AddProperty(tableNode, "table", sizeof(void*) * 2, table);
132
133// Assume the alias pointer is a global or static piece of data
134if (alias != NULL)
135DT__AddProperty(tableNode, "alias", strlen(alias)+1, (char*)alias);
136
137return EFI_SUCCESS;
138}
139return EFI_UNSUPPORTED;
140}
141
142//Azi: crc32 done in place, on the cases were it wasn't.
143/*static inline void fixupEfiSystemTableCRC32(EFI_SYSTEM_TABLE_64 *efiSystemTable)
144{
145efiSystemTable->Hdr.CRC32 = 0;
146efiSystemTable->Hdr.CRC32 = crc32(0L, efiSystemTable, efiSystemTable->Hdr.HeaderSize);
147}*/
148
149/*
150 * What we do here is simply allocate a fake EFI system table and a fake EFI
151 * runtime services table.
152 *
153 * Because we build against modern headers with kBootArgsRevision 4 we
154 * also take care to set efiMode = 32.
155 */
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/*
384 * In addition to the EFI tables there is also the EFI device tree node.
385 * In particular, we need /efi/platform to have an FSBFrequency key. Without it,
386 * the tsc_init function will panic very early on in kernel startup, before
387 * the 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 constgEfiSmbiosTableGuid = EFI_SMBIOS_TABLE_GUID;
405
406#define SMBIOS_RANGE_START0x000F0000
407#define SMBIOS_RANGE_END0x000FFFFF
408
409/* '_SM_' in little endian: */
410#define SMBIOS_ANCHOR_UINT32_LE 0x5f4d535f
411
412#define EFI_ACPI_TABLE_GUID \
413 { \
4140xeb9d2d30, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
415 }
416
417#define EFI_ACPI_20_TABLE_GUID \
418 { \
4190x8868e871, 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/*
443 * Get an smbios option string option to convert to EFI_CHAR16 string
444 */
445
446static EFI_CHAR16* getSmbiosChar16(const char * key, size_t* len)
447{
448const char*src = getStringForKey(key, &bootInfo->smbiosConfig);
449EFI_CHAR16* dst = 0;
450size_t i = 0;
451
452if (!key || !(*key) || !len || !src) return 0;
453
454*len = strlen(src);
455dst = (EFI_CHAR16*) malloc( ((*len)+1) * 2 );
456for (; i < (*len); i++) dst[i] = src[i];
457dst[(*len)] = '\0';
458*len = ((*len)+1)*2; // return the CHAR16 bufsize in cluding zero terminated CHAR16
459return dst;
460}
461
462/*
463 * Get the SystemID from the bios dmi info
464 */
465
466staticEFI_CHAR8* getSmbiosUUID()
467{
468static EFI_CHAR8 uuid[UUID_LEN];
469int i, isZero, isOnes;
470struct SMBEntryPoint*smbios;
471SMBByte*p;
472
473smbios = getSmbios(SMBIOS_PATCHED); // checks for _SM_ anchor and table header checksum
474if (smbios==NULL) return 0; // getSmbios() return a non null value if smbios is found
475
476p = (SMBByte*) FindFirstDmiTableOfType(1, 0x19); // Type 1: (3.3.2) System Information
477if (p==NULL) return NULL;
478
479verbose("Found SMBIOS System Information Table 1\n");
480p += 8;
481
482for (i=0, isZero=1, isOnes=1; i<UUID_LEN; i++)
483{
484if (p[i] != 0x00) isZero = 0;
485if (p[i] != 0xff) isOnes = 0;
486}
487
488if (isZero || isOnes) // empty or setable means: no uuid present
489{
490verbose("No UUID present in SMBIOS System Information Table\n");
491return 0;
492}
493
494memcpy(uuid, p, UUID_LEN);
495return uuid;
496}
497
498/*
499 * return a binary UUID value from the overriden SystemID and SMUUID if found,
500 * or from the bios if not, or from a fixed value if no bios value is found
501 */
502
503static EFI_CHAR8* getSystemID()
504{
505// unable to determine UUID for host. Error: 35 fix
506// Rek: new SMsystemid option conforming to smbios notation standards, this option should
507// belong to smbios config only ...
508const char *sysId = getStringForKey(kSystemID, &bootInfo->bootConfig);
509EFI_CHAR8*ret = getUUIDFromString(sysId);
510
511if (!sysId || !ret) // try bios dmi info UUID extraction
512{
513ret = getSmbiosUUID();
514sysId = 0;
515}
516
517if (!ret) // no bios dmi UUID available, set a fixed value for system-id
518ret=getUUIDFromString((sysId = (const char*) SYSTEM_ID));
519
520verbose("Customizing SystemID with : %s\n", getStringFromUUID(ret)); // apply a nice formatting to the displayed output
521return ret;
522}
523
524/*
525 * Must be called AFTER setup Acpi because we need to take care of correct
526 * facp content to reflect in ioregs
527 */
528
529void setupSystemType()
530{
531Node *node = DT__FindNode("/", false);
532if (node == 0) stop("Couldn't get root node");
533// we need to write this property after facp parsing
534// Export system-type only if it has been overrriden by the SystemType option
535DT__AddProperty(node, SYSTEM_TYPE_PROP, sizeof(Platform.Type), &Platform.Type);
536}
537
538void setupEfiDeviceTree(void)
539{
540EFI_CHAR8* ret = 0;
541EFI_CHAR16* ret16 = 0;
542size_t len = 0;
543Node*node;
544
545node = DT__FindNode("/", false);
546
547if (node == 0) stop("Couldn't get root node");
548
549// We could also just do DT__FindNode("/efi/platform", true)
550// But I think eventually we want to fill stuff in the efi node
551// too so we might as well create it so we have a pointer for it too.
552node = DT__AddChild(node, "efi");
553
554if (archCpuType == CPU_TYPE_I386)
555{
556DT__AddProperty(node, FIRMWARE_ABI_PROP, sizeof(FIRMWARE_ABI_32_PROP_VALUE), (char*)FIRMWARE_ABI_32_PROP_VALUE);
557}
558else
559{
560DT__AddProperty(node, FIRMWARE_ABI_PROP, sizeof(FIRMWARE_ABI_64_PROP_VALUE), (char*)FIRMWARE_ABI_64_PROP_VALUE);
561}
562
563DT__AddProperty(node, FIRMWARE_REVISION_PROP, sizeof(FIRMWARE_REVISION), (EFI_UINT32*)&FIRMWARE_REVISION);
564DT__AddProperty(node, FIRMWARE_VENDOR_PROP, sizeof(FIRMWARE_VENDOR), (EFI_CHAR16*)FIRMWARE_VENDOR);
565
566// TODO: Fill in other efi properties if necessary
567
568// Set up the /efi/runtime-services table node similar to the way a child node of configuration-table
569// is set up. That is, name and table properties
570Node *runtimeServicesNode = DT__AddChild(node, "runtime-services");
571
572if (archCpuType == CPU_TYPE_I386)
573{
574// The value of the table property is the 32-bit physical address for the RuntimeServices table.
575// Since the EFI system table already has a pointer to it, we simply use the address of that pointer
576// for the pointer to the property data. Warning.. DT finalization calls free on that but we're not
577// the only thing to use a non-malloc'd pointer for something in the DT
578
579DT__AddProperty(runtimeServicesNode, "table", sizeof(uint64_t), &gST32->RuntimeServices);
580}
581else
582{
583DT__AddProperty(runtimeServicesNode, "table", sizeof(uint64_t), &gST64->RuntimeServices);
584}
585
586// Set up the /efi/configuration-table node which will eventually have several child nodes for
587// all of the configuration tables needed by various kernel extensions.
588gEfiConfigurationTableNode = DT__AddChild(node, "configuration-table");
589
590// Now fill in the /efi/platform Node
591Node *efiPlatformNode = DT__AddChild(node, "platform");
592
593// NOTE WELL: If you do add FSB Frequency detection, make sure to store
594// the value in the fsbFrequency global and not an malloc'd pointer
595// because the DT_AddProperty function does not copy its args.
596
597if (Platform.CPU.FSBFrequency != 0)
598DT__AddProperty(efiPlatformNode, FSB_Frequency_prop, sizeof(uint64_t), &Platform.CPU.FSBFrequency);
599
600// Export TSC and CPU frequencies for use by the kernel or KEXTs
601if (Platform.CPU.TSCFrequency != 0)
602DT__AddProperty(efiPlatformNode, TSC_Frequency_prop, sizeof(uint64_t), &Platform.CPU.TSCFrequency);
603
604if (Platform.CPU.CPUFrequency != 0)
605DT__AddProperty(efiPlatformNode, CPU_Frequency_prop, sizeof(uint64_t), &Platform.CPU.CPUFrequency);
606
607// Export system-id. Can be disabled with SystemId=No in com.apple.Boot.plist
608if ((ret=getSystemID()))
609DT__AddProperty(efiPlatformNode, SYSTEM_ID_PROP, UUID_LEN, (EFI_UINT32*) ret);
610
611 // Export SystemSerialNumber if present
612if ((ret16=getSmbiosChar16("SMserial", &len)))
613DT__AddProperty(efiPlatformNode, SYSTEM_SERIAL_PROP, len, ret16);
614
615// Export Model if present
616if ((ret16=getSmbiosChar16("SMproductname", &len)))
617DT__AddProperty(efiPlatformNode, MODEL_PROP, len, ret16);
618
619// Fill /efi/device-properties node.
620setupDeviceProperties(node);
621}
622
623/*
624 * Load the smbios.plist override config file if any
625 */
626
627static void setupSmbiosConfigFile(const char *filename)
628{
629chardirSpecSMBIOS[128] = "";
630const char *override_pathname = NULL;
631intlen = 0, err = 0;
632extern void scan_mem();
633
634// Take in account user overriding
635if (getValueForKey(kSMBIOSKey, &override_pathname, &len, &bootInfo->bootConfig) && len > 0)
636{
637// Specify a path to a file, e.g. SMBIOS=/Extra/macProXY.plist
638sprintf(dirSpecSMBIOS, override_pathname);
639err = loadConfigFile(dirSpecSMBIOS, &bootInfo->smbiosConfig);
640}
641else
642{
643// Check selected volume's Extra.
644sprintf(dirSpecSMBIOS, "/Extra/%s", filename);
645if (err = loadConfigFile(dirSpecSMBIOS, &bootInfo->smbiosConfig))
646{
647// Check booter volume/rdbt Extra.
648sprintf(dirSpecSMBIOS, "bt(0,0)/Extra/%s", filename);
649err = loadConfigFile(dirSpecSMBIOS, &bootInfo->smbiosConfig);
650}
651}
652
653if (err)
654{
655verbose("No SMBIOS replacement found.\n");
656}
657
658// get a chance to scan mem dynamically if user asks for it while having the config options loaded as well,
659// as opposed to when it was in scan_platform(); also load the orig. smbios so that we can access dmi info without
660// patching the smbios yet
661getSmbios(SMBIOS_ORIGINAL);
662scan_mem();
663smbios_p = (EFI_PTR32)getSmbios(SMBIOS_PATCHED);// process smbios asap
664}
665
666/*
667 * Installs all the needed configuration table entries
668 */
669
670static void setupEfiConfigurationTable()
671{
672smbios_p = (EFI_PTR32)getSmbios(SMBIOS_PATCHED);
673addConfigurationTable(&gEfiSmbiosTableGuid, &smbios_p, NULL);
674
675// Setup ACPI with DSDT overrides (mackerintel's patch)
676setupAcpi();
677
678// We've obviously changed the count.. so fix up the CRC32
679if (archCpuType == CPU_TYPE_I386)
680{
681gST32->Hdr.CRC32 = 0;
682gST32->Hdr.CRC32 = crc32(0L, gST32, gST32->Hdr.HeaderSize);
683}
684else
685{
686gST64->Hdr.CRC32 = 0;
687gST64->Hdr.CRC32 = crc32(0L, gST64, gST64->Hdr.HeaderSize);
688}
689}
690
691/*
692 * Entrypoint from boot.c
693 */
694
695void setupFakeEfi(void)
696{
697// Generate efi device strings
698setup_pci_devs(root_pci_dev);
699
700// load smbios.plist file if any
701setupSmbiosConfigFile("SMBIOS.plist");
702
703// Initialize the base table
704if (archCpuType == CPU_TYPE_I386)
705{
706setupEfiTables32();
707}
708else
709{
710setupEfiTables64();
711}
712
713// Initialize the device tree
714setupEfiDeviceTree();
715
716// Add configuration table entries to both the services table and the device tree
717setupEfiConfigurationTable();
718}
719
720

Archive Download this file

Revision: 214