Chameleon

Chameleon Svn Source Tree

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

1
2/*
3 * Copyright 2007 David F. Elliott. All rights reserved.
4 */
5//#include "saio_types.h"
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.h"
16#include "device_inject.h"
17#include "convert.h"
18#include "pci.h"
19#include "sl.h"
20#include "failedboot.h"
21#include "appleClut8.h"
22//#include <mach-o/fat.h>
23//#include <mach-o/loader.h>
24
25#if DEBUG
26#define DBG(x...)printf(x)
27#else
28#define DBG(x...)msglog(x)
29#endif
30
31extern void setup_pci_devs(pci_dt_t *pci_dt);
32
33/*
34 * Modern Darwin kernels require some amount of EFI because Apple machines all
35 * have EFI. Modifying the kernel source to not require EFI is of course
36 * possible but would have to be maintained as a separate patch because it is
37 * unlikely that Apple wishes to add legacy support to their kernel.
38 *
39 * As you can see from the Apple-supplied code in bootstruct.c, it seems that
40 * the intention was clearly to modify this booter to provide EFI-like structures
41 * to the kernel rather than modifying the kernel to handle non-EFI stuff. This
42 * makes a lot of sense from an engineering point of view as it means the kernel
43 * for the as yet unreleased EFI-only Macs could still be booted by the non-EFI
44 * DTK systems so long as the kernel checked to ensure the boot tables were
45 * filled in appropriately.Modern xnu requires a system table and a runtime
46 * services table and performs no checks whatsoever to ensure the pointers to
47 * these tables are non-NULL. Therefore, any modern xnu kernel will page fault
48 * early on in the boot process if the system table pointer is zero.
49 *
50 * Even before that happens, the tsc_init function in modern xnu requires the FSB
51 * Frequency to be a property in the /efi/platform node of the device tree or else
52 * it panics the bootstrap process very early on.
53 *
54 * As of this writing, the current implementation found here is good enough
55 * to make the currently available xnu kernel boot without modification on a
56 * system with an appropriate processor. With a minor source modification to
57 * the tsc_init function to remove the explicit check for Core or Core 2
58 * processors the kernel can be made to boot on other processors so long as
59 * the code can be executed by the processor and the machine contains the
60 * necessary hardware.
61 */
62
63/*==========================================================================
64 * Utility function to make a device tree string from an EFI_GUID
65 */
66static inline char * mallocStringForGuid(EFI_GUID const *pGuid)
67{
68char *string = malloc(37);
69efi_guid_unparse_upper(pGuid, string);
70return string;
71}
72
73/*==========================================================================
74 * Function to map 32 bit physical address to 64 bit virtual address
75 */
76static uint64_t ptov64(uint32_t addr)
77{
78return ((uint64_t)addr | 0xFFFFFF8000000000ULL);
79}
80
81// ==========================================================================
82// ErmaC
83static inline uint64_t getCPUTick(void)
84{
85uint32_t lowest;
86uint32_t highest;
87__asm__ volatile ("rdtsc" : "=a" (lowest), "=d" (highest));
88return (uint64_t) highest << 32 | lowest;
89}
90
91/*==========================================================================
92 * Fake EFI implementation
93 */
94
95/* Identify ourselves as the EFI firmware vendor */
96static EFI_CHAR16 const FIRMWARE_VENDOR[] = {'C','h','a','m','e','l','e','o','n','_','2','.','3', 0};
97// Bungo
98//static EFI_UINT32 const FIRMWARE_REVISION = 132; /* FIXME: Find a constant for this. */
99static EFI_UINT32 const FIRMWARE_REVISION = 0x0001000a; // got from real MBP6,1, most Macs use it too
100// Bungo
101/* Default platform system_id (fix by IntVar)
102 static EFI_CHAR8 const SYSTEM_ID[] = "0123456789ABCDEF"; //random value gen by uuidgen
103 */
104
105/* Just a ret instruction */
106static uint8_t const VOIDRET_INSTRUCTIONS[] = {0xc3};
107
108/* movl $0x80000003,%eax; ret */
109static uint8_t const UNSUPPORTEDRET_INSTRUCTIONS_32[] = {0xb8, 0x03, 0x00, 0x00, 0x80, 0xc3};
110static uint8_t const UNSUPPORTEDRET_INSTRUCTIONS_64[] = {0x48, 0xb8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc3};
111
112/* EFI Guides */
113EFI_GUID const gEfiSmbiosTableGuid = EFI_SMBIOS_TABLE_GUID;
114EFI_GUID const gEfiAcpiTableGuid = EFI_ACPI_TABLE_GUID;
115EFI_GUID const gEfiAcpi20TableGuid = EFI_ACPI_20_TABLE_GUID;
116
117EFI_SYSTEM_TABLE_32 *gST32 = NULL;
118EFI_SYSTEM_TABLE_64 *gST64 = NULL;
119Node *gEfiConfigurationTableNode = NULL;
120
121EFI_STATUS addConfigurationTable(EFI_GUID const *pGuid, void *table, char const *alias)
122{
123EFI_UINTN i = 0;
124
125//Azi: as is, cpu's with em64t will use EFI64 on pre 10.6 systems,
126// wich seems to cause no problem. In case it does, force i386 arch.
127if (archCpuType == CPU_TYPE_I386)
128{
129i = gST32->NumberOfTableEntries;
130}
131else
132{
133i = gST64->NumberOfTableEntries;
134}
135
136// We only do adds, not modifications and deletes like InstallConfigurationTable
137if (i >= MAX_CONFIGURATION_TABLE_ENTRIES)
138{
139stop("Fake EFI [ERROR]: Ran out of space for configuration tables [%d]. Increase the reserved size in the code.\n", i);
140}
141
142if (pGuid == NULL)
143{
144return EFI_INVALID_PARAMETER;
145}
146
147if (table != NULL)
148{
149// FIXME
150//((EFI_CONFIGURATION_TABLE_64 *)gST->ConfigurationTable)[i].VendorGuid = *pGuid;
151//((EFI_CONFIGURATION_TABLE_64 *)gST->ConfigurationTable)[i].VendorTable = (EFI_PTR64)table;
152
153//++gST->NumberOfTableEntries;
154
155Node *tableNode = DT__AddChild(gEfiConfigurationTableNode, mallocStringForGuid(pGuid));
156
157// Use the pointer to the GUID we just stuffed into the system table
158DT__AddProperty(tableNode, "guid", sizeof(EFI_GUID), (void *)pGuid);
159
160// The "table" property is the 32-bit (in our implementation) physical address of the table
161DT__AddProperty(tableNode, "table", sizeof(void*) * 2, table);
162
163// Assume the alias pointer is a global or static piece of data
164if (alias != NULL)
165{
166DT__AddProperty(tableNode, "alias", strlen(alias)+1, (char *)alias);
167}
168
169 i++;
170
171 if (archCpuType == CPU_TYPE_I386)
172 {
173 gST32->NumberOfTableEntries = i;
174 }
175 else
176 {
177 gST64->NumberOfTableEntries = i;
178 }
179
180return EFI_SUCCESS;
181}
182return EFI_UNSUPPORTED;
183}
184
185// ==========================================================================
186
187//Azi: crc32 done in place, on the cases were it wasn't.
188/*static inline void fixupEfiSystemTableCRC32(EFI_SYSTEM_TABLE_64 *efiSystemTable)
189{
190efiSystemTable->Hdr.CRC32 = 0;
191efiSystemTable->Hdr.CRC32 = crc32(0L, efiSystemTable, efiSystemTable->Hdr.HeaderSize);
192}*/
193
194/*
195 * What we do here is simply allocate a fake EFI system table and a fake EFI
196 * runtime services table.
197 *
198 * Because we build against modern headers with kBootArgsRevision 4 we
199 * also take care to set efiMode = 32.
200 */
201void setupEfiTables32(void)
202{
203// We use the fake_efi_pages struct so that we only need to do one kernel
204// memory allocation for all needed EFI data. Otherwise, small allocations
205// like the FIRMWARE_VENDOR string would take up an entire page.
206// NOTE WELL: Do NOT assume this struct has any particular layout within itself.
207// It is absolutely not intended to be publicly exposed anywhere
208// We say pages (plural) although right now we are well within the 1 page size
209// and probably will stay that way.
210struct fake_efi_pages
211{
212EFI_SYSTEM_TABLE_32 efiSystemTable;
213EFI_RUNTIME_SERVICES_32 efiRuntimeServices;
214EFI_CONFIGURATION_TABLE_32 efiConfigurationTable[MAX_CONFIGURATION_TABLE_ENTRIES];
215EFI_CHAR16 firmwareVendor[sizeof(FIRMWARE_VENDOR)/sizeof(EFI_CHAR16)];
216uint8_t voidret_instructions[sizeof(VOIDRET_INSTRUCTIONS)/sizeof(uint8_t)];
217uint8_t unsupportedret_instructions[sizeof(UNSUPPORTEDRET_INSTRUCTIONS_32)/sizeof(uint8_t)];
218};
219
220struct fake_efi_pages *fakeEfiPages = (struct fake_efi_pages*)AllocateKernelMemory(sizeof(struct fake_efi_pages));
221
222// Zero out all the tables in case fields are added later
223//bzero(fakeEfiPages, sizeof(struct fake_efi_pages));
224
225// --------------------------------------------------------------------
226// Initialize some machine code that will return EFI_UNSUPPORTED for
227// functions returning int and simply return for void functions.
228memcpy(fakeEfiPages->voidret_instructions, VOIDRET_INSTRUCTIONS, sizeof(VOIDRET_INSTRUCTIONS));
229memcpy(fakeEfiPages->unsupportedret_instructions, UNSUPPORTEDRET_INSTRUCTIONS_32, sizeof(UNSUPPORTEDRET_INSTRUCTIONS_32));
230
231// --------------------------------------------------------------------
232// System table
233EFI_SYSTEM_TABLE_32 *efiSystemTable = gST32 = &fakeEfiPages->efiSystemTable;
234efiSystemTable->Hdr.Signature = EFI_SYSTEM_TABLE_SIGNATURE;
235efiSystemTable->Hdr.Revision = EFI_SYSTEM_TABLE_REVISION;
236efiSystemTable->Hdr.HeaderSize = sizeof(EFI_SYSTEM_TABLE_32);
237efiSystemTable->Hdr.CRC32 = 0; // Initialize to zero and then do CRC32
238efiSystemTable->Hdr.Reserved = 0;
239
240efiSystemTable->FirmwareVendor = (EFI_PTR32)&fakeEfiPages->firmwareVendor;
241memcpy(fakeEfiPages->firmwareVendor, FIRMWARE_VENDOR, sizeof(FIRMWARE_VENDOR));
242efiSystemTable->FirmwareRevision = FIRMWARE_REVISION;
243
244// XXX: We may need to have basic implementations of ConIn/ConOut/StdErr
245// The EFI spec states that all handles are invalid after boot services have been
246// exited so we can probably get by with leaving the handles as zero.
247efiSystemTable->ConsoleInHandle = 0;
248efiSystemTable->ConIn = 0;
249
250efiSystemTable->ConsoleOutHandle = 0;
251efiSystemTable->ConOut = 0;
252
253efiSystemTable->StandardErrorHandle = 0;
254efiSystemTable->StdErr = 0;
255
256efiSystemTable->RuntimeServices = (EFI_PTR32)&fakeEfiPages->efiRuntimeServices;
257
258// According to the EFI spec, BootServices aren't valid after the
259// boot process is exited so we can probably do without it.
260// Apple didn't provide a definition for it in pexpert/i386/efi.h
261// so I'm guessing they don't use it.
262efiSystemTable->BootServices = 0;
263
264efiSystemTable->NumberOfTableEntries = 0;
265efiSystemTable->ConfigurationTable = (EFI_PTR32)fakeEfiPages->efiConfigurationTable;
266
267// We're done. Now CRC32 the thing so the kernel will accept it.
268// Must be initialized to zero before CRC32, done above.
269gST32->Hdr.CRC32 = crc32(0L, gST32, gST32->Hdr.HeaderSize);
270
271// --------------------------------------------------------------------
272// Runtime services
273EFI_RUNTIME_SERVICES_32 *efiRuntimeServices = &fakeEfiPages->efiRuntimeServices;
274efiRuntimeServices->Hdr.Signature = EFI_RUNTIME_SERVICES_SIGNATURE;
275efiRuntimeServices->Hdr.Revision = EFI_RUNTIME_SERVICES_REVISION;
276efiRuntimeServices->Hdr.HeaderSize = sizeof(EFI_RUNTIME_SERVICES_32);
277efiRuntimeServices->Hdr.CRC32 = 0;
278efiRuntimeServices->Hdr.Reserved = 0;
279
280// There are a number of function pointers in the efiRuntimeServices table.
281// These are the Foundation (e.g. core) services and are expected to be present on
282// all EFI-compliant machines.Some kernel extensions (notably AppleEFIRuntime)
283// will call these without checking to see if they are null.
284//
285// We don't really feel like doing an EFI implementation in the bootloader
286// but it is nice if we can at least prevent a complete crash by
287// at least providing some sort of implementation until one can be provided
288// nicely in a kext.
289void (*voidret_fp)() = (void*)fakeEfiPages->voidret_instructions;
290void (*unsupportedret_fp)() = (void*)fakeEfiPages->unsupportedret_instructions;
291efiRuntimeServices->GetTime = (EFI_PTR32)unsupportedret_fp;
292efiRuntimeServices->SetTime = (EFI_PTR32)unsupportedret_fp;
293efiRuntimeServices->GetWakeupTime = (EFI_PTR32)unsupportedret_fp;
294efiRuntimeServices->SetWakeupTime = (EFI_PTR32)unsupportedret_fp;
295efiRuntimeServices->SetVirtualAddressMap = (EFI_PTR32)unsupportedret_fp;
296efiRuntimeServices->ConvertPointer = (EFI_PTR32)unsupportedret_fp;
297efiRuntimeServices->GetVariable = (EFI_PTR32)unsupportedret_fp;
298efiRuntimeServices->GetNextVariableName = (EFI_PTR32)unsupportedret_fp;
299efiRuntimeServices->SetVariable = (EFI_PTR32)unsupportedret_fp;
300efiRuntimeServices->GetNextHighMonotonicCount = (EFI_PTR32)unsupportedret_fp;
301efiRuntimeServices->ResetSystem = (EFI_PTR32)voidret_fp;
302
303// We're done.Now CRC32 the thing so the kernel will accept it
304efiRuntimeServices->Hdr.CRC32 = crc32(0L, efiRuntimeServices, efiRuntimeServices->Hdr.HeaderSize);
305
306// --------------------------------------------------------------------
307// Finish filling in the rest of the boot args that we need.
308bootArgs->efiSystemTable = (uint32_t)efiSystemTable;
309bootArgs->efiMode = kBootArgsEfiMode32;
310
311// The bootArgs structure as a whole is bzero'd so we don't need to fill in
312// things like efiRuntimeServices* and what not.
313//
314// In fact, the only code that seems to use that is the hibernate code so it
315// knows not to save the pages. It even checks to make sure its nonzero.
316}
317
318void setupEfiTables64(void)
319{
320struct fake_efi_pages
321{
322EFI_SYSTEM_TABLE_64 efiSystemTable;
323EFI_RUNTIME_SERVICES_64 efiRuntimeServices;
324EFI_CONFIGURATION_TABLE_64 efiConfigurationTable[MAX_CONFIGURATION_TABLE_ENTRIES];
325EFI_CHAR16 firmwareVendor[sizeof(FIRMWARE_VENDOR)/sizeof(EFI_CHAR16)];
326uint8_t voidret_instructions[sizeof(VOIDRET_INSTRUCTIONS)/sizeof(uint8_t)];
327uint8_t unsupportedret_instructions[sizeof(UNSUPPORTEDRET_INSTRUCTIONS_64)/sizeof(uint8_t)];
328};
329
330struct fake_efi_pages *fakeEfiPages = (struct fake_efi_pages*)AllocateKernelMemory(sizeof(struct fake_efi_pages));
331
332// Zero out all the tables in case fields are added later
333//bzero(fakeEfiPages, sizeof(struct fake_efi_pages));
334
335// --------------------------------------------------------------------
336// Initialize some machine code that will return EFI_UNSUPPORTED for
337// functions returning int and simply return for void functions.
338memcpy(fakeEfiPages->voidret_instructions, VOIDRET_INSTRUCTIONS, sizeof(VOIDRET_INSTRUCTIONS));
339memcpy(fakeEfiPages->unsupportedret_instructions, UNSUPPORTEDRET_INSTRUCTIONS_64, sizeof(UNSUPPORTEDRET_INSTRUCTIONS_64));
340
341// --------------------------------------------------------------------
342// System table
343EFI_SYSTEM_TABLE_64 *efiSystemTable = gST64 = &fakeEfiPages->efiSystemTable;
344efiSystemTable->Hdr.Signature = EFI_SYSTEM_TABLE_SIGNATURE;
345efiSystemTable->Hdr.Revision = EFI_SYSTEM_TABLE_REVISION;
346efiSystemTable->Hdr.HeaderSize = sizeof(EFI_SYSTEM_TABLE_64);
347efiSystemTable->Hdr.CRC32 = 0; // Initialize to zero and then do CRC32
348efiSystemTable->Hdr.Reserved = 0;
349
350efiSystemTable->FirmwareVendor = ptov64((EFI_PTR32)&fakeEfiPages->firmwareVendor);
351memcpy(fakeEfiPages->firmwareVendor, FIRMWARE_VENDOR, sizeof(FIRMWARE_VENDOR));
352efiSystemTable->FirmwareRevision = FIRMWARE_REVISION;
353
354// XXX: We may need to have basic implementations of ConIn/ConOut/StdErr
355// The EFI spec states that all handles are invalid after boot services have been
356// exited so we can probably get by with leaving the handles as zero.
357efiSystemTable->ConsoleInHandle = 0;
358efiSystemTable->ConIn = 0;
359
360efiSystemTable->ConsoleOutHandle = 0;
361efiSystemTable->ConOut = 0;
362
363efiSystemTable->StandardErrorHandle = 0;
364efiSystemTable->StdErr = 0;
365
366efiSystemTable->RuntimeServices = ptov64((EFI_PTR32)&fakeEfiPages->efiRuntimeServices);
367// According to the EFI spec, BootServices aren't valid after the
368// boot process is exited so we can probably do without it.
369// Apple didn't provide a definition for it in pexpert/i386/efi.h
370// so I'm guessing they don't use it.
371efiSystemTable->BootServices = 0;
372
373efiSystemTable->NumberOfTableEntries = 0;
374efiSystemTable->ConfigurationTable = ptov64((EFI_PTR32)fakeEfiPages->efiConfigurationTable);
375
376// We're done.Now CRC32 the thing so the kernel will accept it
377gST64->Hdr.CRC32 = crc32(0L, gST64, gST64->Hdr.HeaderSize);
378
379// --------------------------------------------------------------------
380// Runtime services
381EFI_RUNTIME_SERVICES_64 *efiRuntimeServices = &fakeEfiPages->efiRuntimeServices;
382efiRuntimeServices->Hdr.Signature = EFI_RUNTIME_SERVICES_SIGNATURE;
383efiRuntimeServices->Hdr.Revision = EFI_RUNTIME_SERVICES_REVISION;
384efiRuntimeServices->Hdr.HeaderSize = sizeof(EFI_RUNTIME_SERVICES_64);
385efiRuntimeServices->Hdr.CRC32 = 0;
386efiRuntimeServices->Hdr.Reserved = 0;
387
388// There are a number of function pointers in the efiRuntimeServices table.
389// These are the Foundation (e.g. core) services and are expected to be present on
390// all EFI-compliant machines.Some kernel extensions (notably AppleEFIRuntime)
391// will call these without checking to see if they are null.
392//
393// We don't really feel like doing an EFI implementation in the bootloader
394// but it is nice if we can at least prevent a complete crash by
395// at least providing some sort of implementation until one can be provided
396// nicely in a kext.
397
398void (*voidret_fp)() = (void*)fakeEfiPages->voidret_instructions;
399void (*unsupportedret_fp)() = (void*)fakeEfiPages->unsupportedret_instructions;
400efiRuntimeServices->GetTime = ptov64((EFI_PTR32)unsupportedret_fp);
401efiRuntimeServices->SetTime = ptov64((EFI_PTR32)unsupportedret_fp);
402efiRuntimeServices->GetWakeupTime = ptov64((EFI_PTR32)unsupportedret_fp);
403efiRuntimeServices->SetWakeupTime = ptov64((EFI_PTR32)unsupportedret_fp);
404efiRuntimeServices->SetVirtualAddressMap = ptov64((EFI_PTR32)unsupportedret_fp);
405efiRuntimeServices->ConvertPointer = ptov64((EFI_PTR32)unsupportedret_fp);
406efiRuntimeServices->GetVariable = ptov64((EFI_PTR32)unsupportedret_fp);
407efiRuntimeServices->GetNextVariableName = ptov64((EFI_PTR32)unsupportedret_fp);
408efiRuntimeServices->SetVariable = ptov64((EFI_PTR32)unsupportedret_fp);
409efiRuntimeServices->GetNextHighMonotonicCount = ptov64((EFI_PTR32)unsupportedret_fp);
410efiRuntimeServices->ResetSystem = ptov64((EFI_PTR32)voidret_fp);
411
412// We're done.Now CRC32 the thing so the kernel will accept it
413efiRuntimeServices->Hdr.CRC32 = crc32(0L, efiRuntimeServices, efiRuntimeServices->Hdr.HeaderSize);
414
415// --------------------------------------------------------------------
416// Finish filling in the rest of the boot args that we need.
417bootArgs->efiSystemTable = (uint32_t)efiSystemTable;
418bootArgs->efiMode = kBootArgsEfiMode64;
419
420// The bootArgs structure as a whole is bzero'd so we don't need to fill in
421// things like efiRuntimeServices* and what not.
422//
423// In fact, the only code that seems to use that is the hibernate code so it
424// knows not to save the pages. It even checks to make sure its nonzero.
425}
426
427/*
428 * In addition to the EFI tables there is also the EFI device tree node.
429 * In particular, we need /efi/platform to have an FSBFrequency key. Without it,
430 * the tsc_init function will panic very early on in kernel startup, before
431 * the console is available.
432 */
433
434/*==========================================================================
435 * FSB Frequency detection
436 */
437
438/* These should be const but DT__AddProperty takes char* */
439static const char TSC_Frequency_prop[] = "TSCFrequency";
440static const char FSB_Frequency_prop[] = "FSBFrequency";
441static const char CPU_Frequency_prop[] = "CPUFrequency";
442
443/*==========================================================================
444 * Fake EFI implementation
445 */
446
447/* These should be const but DT__AddProperty takes char* */
448static const char FIRMWARE_REVISION_PROP[] = "firmware-revision";
449static const char FIRMWARE_ABI_PROP[] = "firmware-abi";
450static const char FIRMWARE_VENDOR_PROP[] = "firmware-vendor";
451//static const char FIRMWARE_ABI_32_PROP_VALUE[] = "EFI32";
452static const char FIRMWARE_ABI_64_PROP_VALUE[] = "EFI64";
453static const char EFI_MODE_PROP[] = "efi-mode"; //Bungo
454static const char SYSTEM_ID_PROP[] = "system-id";
455static const char SYSTEM_SERIAL_PROP[] = "SystemSerialNumber";
456static const char SYSTEM_TYPE_PROP[] = "system-type";
457static const char MODEL_PROP[] = "Model";
458static const char BOARDID_PROP[] = "board-id";
459static const char DEV_PATHS_SUP_PROP[] = "DevicePathsSupported";
460static const char MACHINE_SIG_PROP[] = "machine-signature";
461static EFI_UINT32 const ZERO_U32 = 0;
462static EFI_UINT32 const ONE_U32 = 1;
463static const char RANDOM_SEED_PROP[] = "random-seed";
464/*
465static EFI_UINT8 const RANDOM_SEED_PROP_VALUE[] =
466{
467 0x40, 0x00, 0x50, 0x00, 0x5c, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00,
468 0x6d, 0x00, 0x5c, 0x00, 0x4c, 0x00, 0x69, 0x00, 0x62, 0x00, 0x72, 0x00, 0x61, 0x00, 0x72, 0x00,
469 0x79, 0x00, 0x5c, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x53, 0x00, 0x65, 0x00,
470 0x72, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x5c, 0x00, 0x62, 0x00
471}; */
472
473/*
474 * Get an smbios option string option to convert to EFI_CHAR16 string
475 */
476static EFI_CHAR16* getSmbiosChar16(const char * key, size_t* len)
477{
478const char*src = getStringForKey(key, &bootInfo->smbiosConfig);
479EFI_CHAR16* dst = 0;
480size_t i = 0;
481
482if (!key || !(*key) || !len || !src)
483{
484return 0;
485}
486
487*len = strlen(src);
488dst = (EFI_CHAR16*) malloc( ((*len)+1) * 2 );
489for (; i < (*len); i++)
490{
491dst[i] = src[i];
492}
493dst[(*len)] = '\0';
494*len = ((*len)+1)*2; // return the CHAR16 bufsize including zero terminated CHAR16
495return dst;
496}
497
498// Bungo
499/*
500 * Get the SystemID from the bios dmi info
501
502staticEFI_CHAR8* getSmbiosUUID()
503{
504static EFI_CHAR8 uuid[UUID_LEN];
505int i, isZero, isOnes;
506SMBByte*p;
507
508p = (SMBByte*)Platform.UUID;
509
510for (i=0, isZero=1, isOnes=1; i<UUID_LEN; i++)
511{
512if (p[i] != 0x00)
513{
514isZero = 0;
515}
516
517if (p[i] != 0xff)
518{
519isOnes = 0;
520}
521}
522
523if (isZero || isOnes) // empty or setable means: no uuid present
524{
525verbose("No UUID present in SMBIOS System Information Table\n");
526return 0;
527}
528
529memcpy(uuid, p, UUID_LEN);
530return uuid;
531}
532
533
534// return a binary UUID value from the overriden SystemID and SMUUID if found,
535// or from the bios if not, or from a fixed value if no bios value is found
536
537static EFI_CHAR8* getSystemID()
538{
539// unable to determine UUID for host. Error: 35 fix
540// Rek: new SMsystemid option conforming to smbios notation standards, this option should
541// belong to smbios config only ...
542const char *sysId = getStringForKey(kSystemID, &bootInfo->chameleonConfig);
543EFI_CHAR8*ret = getUUIDFromString(sysId);
544
545if (!sysId || !ret) // try bios dmi info UUID extraction
546{
547ret = getSmbiosUUID();
548sysId = 0;
549}
550
551if (!ret)
552{
553// no bios dmi UUID available, set a fixed value for system-id
554ret=getUUIDFromString((sysId = (const char*) SYSTEM_ID));
555}
556verbose("Customizing SystemID with : %s\n", getStringFromUUID(ret)); // apply a nice formatting to the displayed output
557return ret;
558}
559 */
560
561/*
562 * Must be called AFTER setupAcpi because we need to take care of correct
563 * FACP content to reflect in ioregs
564 */
565void setupSystemType()
566{
567Node *node = DT__FindNode("/", false);
568if (node == 0)
569{
570stop("Couldn't get root '/' node");
571}
572// we need to write this property after facp parsing
573// Export system-type only if it has been overrriden by the SystemType option
574DT__AddProperty(node, SYSTEM_TYPE_PROP, sizeof(Platform.Type), &Platform.Type);
575}
576
577bool getKernelCompat(EFI_UINT8 *compat)
578{
579 int kernelFileRef;
580 EFI_UINT8 readBytes;
581 char kernelFilePath[512], kernelHeaderBuf[sizeof(struct fat_header) + 4*sizeof(struct fat_arch)];
582
583 snprintf(kernelFilePath, sizeof(kernelFilePath), "%s", bootInfo->bootFile);
584 //strlcpy(kernelFilePath, bootInfo->bootFile, sizeof(kernelFilePath)); // user defined path
585 DBG("EfiKernelCompat: trying to read kernel header from file '%s'...\n", kernelFilePath);
586 if ((kernelFileRef = open(kernelFilePath, 0)) >= 0) {
587 } else {
588 snprintf(kernelFilePath, sizeof(kernelFilePath), "/%s", bootInfo->bootFile); // append a leading '/'
589 DBG("EfiKernelCompat: trying to read kernel header from file '%s'...\n", kernelFilePath);
590 if ((kernelFileRef = open(kernelFilePath, 0)) >= 0) {
591 } else {
592 snprintf(kernelFilePath, sizeof(kernelFilePath), "/System/Library/Kernels/%s", bootInfo->bootFile); // Yosemite path
593 DBG("EfiKernelCompat: trying to read kernel header from file '%s'...\n", kernelFilePath);
594 if ((kernelFileRef = open(kernelFilePath, 0)) >= 0) {
595 } else {
596 DBG("EfiKernelCompat: can't find any kernel file!\n");
597 return false;
598 }
599 }
600 }
601
602 if ((readBytes = read(kernelFileRef, kernelHeaderBuf, sizeof(struct fat_header) + 4*sizeof(struct fat_arch))) > 0) {
603 DBG("EfiKernelCompat: OK, read %d bytes from file '%s'.\n", readBytes, kernelFilePath);
604 } else {
605 DBG("EfiKernelCompat: can't read kernel file '%s'!\n", kernelFilePath);
606 return false;
607 }
608
609 struct fat_header *fatHeaderPtr = (struct fat_header *)kernelHeaderBuf;
610struct fat_arch *fatArchPtr = (struct fat_arch *)(kernelHeaderBuf + sizeof(struct fat_header));
611 struct mach_header *thinHeaderPtr = (struct mach_header *)kernelHeaderBuf;
612 bool swapit = false;
613
614 switch (fatHeaderPtr->magic) {
615 case FAT_CIGAM:
616 swapit = true;
617 fatHeaderPtr->nfat_arch = OSSwapInt32(fatHeaderPtr->nfat_arch);
618 case FAT_MAGIC:
619 *compat = 0;
620 DBG("EfiKernelCompat: kernel file is a fat binary: %d archs compatibility [", fatHeaderPtr->nfat_arch);
621 if (fatHeaderPtr->nfat_arch > 4) fatHeaderPtr->nfat_arch = 4;
622 for (; fatHeaderPtr->nfat_arch > 0; fatHeaderPtr->nfat_arch--, fatArchPtr++) {
623 if (swapit) fatArchPtr->cputype = OSSwapInt32(fatArchPtr->cputype);
624 switch(fatArchPtr->cputype) {
625 case CPU_TYPE_I386:
626 DBG(" i386");
627 break;
628 case CPU_TYPE_X86_64:
629 DBG(" x86_64");
630 break;
631 case CPU_TYPE_POWERPC:
632 DBG(" PPC");
633 break;
634 case CPU_TYPE_POWERPC64:
635 DBG(" PPC64");
636 break;
637 default:
638 DBG(" 0x%x", fatArchPtr->cputype);
639 }
640 if (fatHeaderPtr->nfat_arch - 1 > 0) DBG(" | ");
641 *compat |= (!(fatArchPtr->cputype ^ CPU_TYPE_I386) << 0) | (!(fatArchPtr->cputype ^ CPU_TYPE_X86_64) << 1) | (!(fatArchPtr->cputype ^ CPU_TYPE_POWERPC) << 2) | (!(fatArchPtr->cputype ^ CPU_TYPE_POWERPC64) << 3);
642 }
643 DBG(" ]\n");
644 break;
645 case MH_CIGAM:
646 case MH_CIGAM_64:
647 thinHeaderPtr->cputype = OSSwapInt32(thinHeaderPtr->cputype);
648 case MH_MAGIC:
649 case MH_MAGIC_64:
650 *compat = (!(thinHeaderPtr->cputype ^ CPU_TYPE_I386) << 0) | (!(thinHeaderPtr->cputype ^ CPU_TYPE_X86_64) << 1) | (!(thinHeaderPtr->cputype ^ CPU_TYPE_POWERPC) << 2) | (!(thinHeaderPtr->cputype ^ CPU_TYPE_POWERPC64) << 3);
651 DBG("EfiKernelCompat: kernel file is a thin binary: 1 arch compatibility found [ %s ].\n", !((thinHeaderPtr->cputype & 0x000000FF) ^ 0x00000007) ? (!((thinHeaderPtr->cputype & 0xFF000000) ^ 0x01000000) ? "x86_64" : "i386") : (!((thinHeaderPtr->cputype & 0xFF000000) ^ 0x01000000) ? "PPC64" : "PPC"));
652 break;
653 default:
654 DBG("EfiKernelCompat: unknown kernel file '%s'. Can't determine arch compatibility!\n", kernelFilePath);
655 return false;
656 }
657
658 return true;
659}
660
661/*
662 * Installs all the needed configuration table entries
663 */
664static void setupEfiConfigurationTable()
665{
666// smbios_p = (EFI_PTR32)getSmbios(SMBIOS_PATCHED);
667if (smbios_p) {
668 if (EFI_SUCCESS == addConfigurationTable(&gEfiSmbiosTableGuid, &smbios_p, NULL)) {
669 DBG("Fake EFI: sucesfuly added %sbit configuration table for SMBIOS: guid {EB9D2D31-2D88-11D3-9A16-0090273FC14D}.\n", (archCpuType == CPU_TYPE_I386) ? "32":"64");
670 }
671 }
672
673// Setup ACPI with DSDT overrides (mackerintel's patch)
674//setupAcpi();
675
676 if (acpi10_p) {
677 if (EFI_SUCCESS == addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI")) {
678 DBG("Fake EFI: sucesfuly added %sbit configuration table for ACPI: guid {EB9D2D30-2D88-11D3-9A16-0090273FC14D}.\n", (archCpuType == CPU_TYPE_I386) ? "32":"64");
679 }
680 }
681 if (acpi20_p) {
682 if (EFI_SUCCESS == addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20")) {
683 DBG("Fake EFI: sucesfuly added %sbit configuration table for ACPI_20: guid {8868E871-E4F1-11D3-BC22-0080C73C8881}.\n", (archCpuType == CPU_TYPE_I386) ? "32":"64");
684 }
685 }
686
687// We've obviously changed the count.. so fix up the CRC32
688if (archCpuType == CPU_TYPE_I386)
689{
690gST32->Hdr.CRC32 = 0;
691gST32->Hdr.CRC32 = crc32(0L, gST32, gST32->Hdr.HeaderSize);
692}
693else
694{
695gST64->Hdr.CRC32 = 0;
696gST64->Hdr.CRC32 = crc32(0L, gST64, gST64->Hdr.HeaderSize);
697}
698}
699
700void setupEfiNode(void)
701{
702EFI_CHAR16* ret16 = 0;
703size_t len = 0;
704
705Node *efiNode = DT__FindNode("/efi", true);
706 if (efiNode == 0)
707{
708stop("Couldn't get '/efi' node");
709}
710
711/* Bungo: we have 64 bit ability fake efi but mode may be changed 32/64, like Macs
712if (archCpuType == CPU_TYPE_I386) {
713DT__AddProperty(efiNode, FIRMWARE_ABI_PROP, sizeof(FIRMWARE_ABI_32_PROP_VALUE), (EFI_CHAR8 *)FIRMWARE_ABI_32_PROP_VALUE);
714} else { */
715DT__AddProperty(efiNode, FIRMWARE_ABI_PROP, sizeof(FIRMWARE_ABI_64_PROP_VALUE), (EFI_CHAR8 *)FIRMWARE_ABI_64_PROP_VALUE);
716//}
717// So, added 'efi-mode' property to tell us what mode we use 32 or 64 bit
718DT__AddProperty(efiNode, EFI_MODE_PROP, sizeof(EFI_UINT8), (EFI_UINT8 *)&bootArgs->efiMode);
719
720DT__AddProperty(efiNode, FIRMWARE_REVISION_PROP, sizeof(FIRMWARE_REVISION), (EFI_UINT32 *)&FIRMWARE_REVISION);
721DT__AddProperty(efiNode, FIRMWARE_VENDOR_PROP, sizeof(FIRMWARE_VENDOR), (EFI_CHAR16 *)&FIRMWARE_VENDOR);
722
723// TODO: Fill in other efi properties if necessary
724
725// Set up the /efi/runtime-services table node similar to the way a child node of configuration-table
726// is set up. That is, name and table properties
727Node *runtimeServicesNode = DT__AddChild(efiNode, "runtime-services");
728
729if (archCpuType == CPU_TYPE_I386) {
730// The value of the table property is the 32-bit physical address for the RuntimeServices table.
731// Since the EFI system table already has a pointer to it, we simply use the address of that pointer
732// for the pointer to the property data. Warning.. DT finalization calls free on that but we're not
733// the only thing to use a non-malloc'd pointer for something in the DT
734DT__AddProperty(runtimeServicesNode, "table", sizeof(EFI_UINT64), &gST32->RuntimeServices);
735} else {
736DT__AddProperty(runtimeServicesNode, "table", sizeof(EFI_UINT64), &gST64->RuntimeServices);
737}
738
739// Set up the /efi/configuration-table node which will eventually have several child nodes for
740// all of the configuration tables needed by various kernel extensions.
741gEfiConfigurationTableNode = DT__AddChild(efiNode, "configuration-table");
742
743// Set up the /efi/kernel-compatibility node only if 10.7 or better
744 if (MacOSVerCurrent >= MacOSVer2Int("10.7")) {
745 Node *EfiKernelCompatNode = DT__AddChild(efiNode, "kernel-compatibility");
746 EFI_UINT8 compat = (archCpuType == CPU_TYPE_I386) ? 0b00000001 : 0b00000010;
747 getKernelCompat(&compat);
748 if (compat & 0b00000001) DT__AddProperty(EfiKernelCompatNode, "i386", sizeof(EFI_UINT32), (EFI_UINT32 *)&ONE_U32);
749 if (compat & 0b00000010) DT__AddProperty(EfiKernelCompatNode, "x86_64", sizeof(EFI_UINT32), (EFI_UINT32 *)&ONE_U32);
750 if (compat & 0b00000100) DT__AddProperty(EfiKernelCompatNode, "PPC", sizeof(EFI_UINT32), (EFI_UINT32 *)&ONE_U32);
751 if (compat & 0b00001000) DT__AddProperty(EfiKernelCompatNode, "PPC64", sizeof(EFI_UINT32), (EFI_UINT32 *)&ONE_U32);
752 }
753
754// Now fill in the /efi/platform Node
755Node *efiPlatformNode = DT__AddChild(efiNode, "platform");
756
757// NOTE WELL: If you do add FSB Frequency detection, make sure to store
758// the value in the fsbFrequency global and not an malloc'd pointer
759// because the DT_AddProperty function does not copy its args.
760
761if (Platform.CPU.FSBFrequency != 0) {
762DT__AddProperty(efiPlatformNode, FSB_Frequency_prop, sizeof(EFI_UINT64), (EFI_UINT64 *)&Platform.CPU.FSBFrequency);
763}
764
765// Export TSC and CPU frequencies for use by the kernel or KEXTs
766if (Platform.CPU.TSCFrequency != 0) {
767DT__AddProperty(efiPlatformNode, TSC_Frequency_prop, sizeof(EFI_UINT64), (EFI_UINT64 *)&Platform.CPU.TSCFrequency);
768}
769
770if (Platform.CPU.CPUFrequency != 0) {
771DT__AddProperty(efiPlatformNode, CPU_Frequency_prop, sizeof(EFI_UINT64), (EFI_UINT64 *)&Platform.CPU.CPUFrequency);
772}
773
774DT__AddProperty(efiPlatformNode, DEV_PATHS_SUP_PROP, sizeof(EFI_UINT32), (EFI_UINT32 *)&ONE_U32);
775
776// Bungo
777/* Export system-id. Can be disabled with SystemId=No in com.apple.Boot.plist
778if ((ret=getSystemID())) {
779DT__AddProperty(efiPlatformNode, SYSTEM_ID_PROP, UUID_LEN, (EFI_UINT32*) ret);
780}
781*/
782DT__AddProperty(efiPlatformNode, SYSTEM_ID_PROP, UUID_LEN, Platform.UUID);
783
784// Export SystemSerialNumber if present
785if ((ret16=getSmbiosChar16("SMserial", &len))) {
786DT__AddProperty(efiPlatformNode, SYSTEM_SERIAL_PROP, len, ret16);
787}
788
789// Export Model if present
790if ((ret16=getSmbiosChar16("SMproductname", &len))) {
791DT__AddProperty(efiPlatformNode, MODEL_PROP, len, ret16);
792}
793
794// Fill /efi/device-properties.
795setupDeviceProperties(efiNode);
796
797 // Add configuration table entries to both the services table and the device tree
798setupEfiConfigurationTable();
799}
800
801/*
802 * Must be called AFTER getSmbios
803 */
804void setupBoardId()
805{
806Node *node;
807node = DT__FindNode("/", false);
808if (node == 0)
809{
810stop("Couldn't get root '/' node");
811}
812const char *boardid = getStringForKey("SMboardproduct", &bootInfo->smbiosConfig);
813if (boardid)
814{
815DT__AddProperty(node, BOARDID_PROP, strlen(boardid) + 1, (EFI_CHAR16 *)boardid);
816}
817}
818
819/*
820 * Fill up the root node
821 *
822setupRootNode()
823{
824
825}
826*/
827/*
828 * Fill up the chosen node
829 */
830void setupChosenNode()
831{
832Node *chosenNode = DT__FindNode("/chosen", false);
833if (chosenNode == 0) {
834stop("setupChosenNode: Couldn't get '/chosen' node");
835}
836
837 // Add boot-uuid property
838int length = strlen(gBootUUIDString);
839if (length) {
840DT__AddProperty(chosenNode, "boot-uuid", length + 1, gBootUUIDString);
841}
842
843 // Add boot-args property
844length = strlen(bootArgs->CommandLine);
845DT__AddProperty(chosenNode, "boot-args", length + 1, bootArgs->CommandLine);
846
847 // Add boot-file property
848length = strlen(bootInfo->bootFile);
849DT__AddProperty(chosenNode, "boot-file", length + 1, bootInfo->bootFile);
850
851 // TODO:
852 //DT__AddProperty(chosenNode, "boot-device-path", bootDPsize, gBootDP);
853 //DT__AddProperty(chosenNode, "boot-file-path", bootFPsize, gBootFP);
854 //DT__AddProperty(chosenNode, "boot-kernelchache-adler32", sizeof(adler32), adler32);
855
856 // Add machine-signature property
857DT__AddProperty(chosenNode, MACHINE_SIG_PROP, sizeof(EFI_UINT32), (EFI_UINT32 *)&Platform.HWSignature);
858
859//if(YOSEMITE)
860 if (MacOSVerCurrent >= MacOSVer2Int("10.10")) // Add random-seed property if Yosemite or better only
861{
862//
863// Pike R. Alpha - 12 October 2014
864//
865UInt8 index = 0;
866EFI_UINT16 PMTimerValue = 0;
867EFI_UINT32 randomValue, tempValue, cpuTick;
868EFI_UINT32 ecx, esi, edi = 0;
869EFI_UINT32 rcx, rdx, rsi, rdi;
870
871randomValue = tempValue = ecx = esi = edi = 0;// xor%ecx,%ecx
872rcx = rdx = rsi = rdi = cpuTick = 0;
873
874// LEAF_1 - Feature Information (Function 01h).
875if (Platform.CPU.CPUID[CPUID_1][2] & 0x40000000)// Checking ecx:bit-30
876{
877//
878// i5/i7 Ivy Bridge and Haswell processors with RDRAND support.
879//
880EFI_UINT32 seedBuffer[16] = {0};
881//
882// Main loop to get 16 qwords (four bytes each).
883//
884for (index = 0; index < 16; index++)// 0x17e12:
885{
886randomValue = computeRand();// callq0x18e20
887cpuTick = getCPUTick();// callq0x121a7
888randomValue = (randomValue ^ cpuTick);// xor%rdi,%rax
889seedBuffer[index] = randomValue;// mov%rax,(%r15,%rsi,8)
890}// jb0x17e12
891
892DT__AddProperty(chosenNode, RANDOM_SEED_PROP, sizeof(seedBuffer), (EFI_UINT32*) &seedBuffer);
893}
894else
895{
896//
897// All other processors without RDRAND support.
898//
899EFI_UINT8 seedBuffer[64] = {0};
900//
901// Main loop to get the 64 bytes.
902//
903do// 0x17e55:
904{
905PMTimerValue = inw(0x408);// in(%dx),%ax
906esi = PMTimerValue;// movzwl%ax,%esi
907
908if (esi < ecx)// cmp%ecx,%esi
909{
910continue;// jb0x17e55(retry)
911}
912
913cpuTick = getCPUTick();// callq0x121a7
914rcx = (cpuTick >> 8);// mov%rax,%rcx
915// shr$0x8,%rcx
916rdx = (cpuTick >> 10);// mov%rax,%rdx
917// shr$0x10,%rdx
918rdi = rsi;// mov%rsi,%rdi
919rdi = (rdi ^ cpuTick);// xor%rax,%rdi
920rdi = (rdi ^ rcx);// xor%rcx,%rdi
921rdi = (rdi ^ rdx);// xor%rdx,%rdi
922
923seedBuffer[index] = (rdi & 0xff);// mov%dil,(%r15,%r12,1)
924
925edi = (edi & 0x2f);// and$0x2f,%edi
926edi = (edi + esi);// add%esi,%edi
927index++;// incr12
928ecx = (edi & 0xffff);// movzwl%di,%ecx
929
930} while (index < 64);// cmp%r14d,%r12d
931// jne0x17e55(next)
932
933DT__AddProperty(chosenNode, RANDOM_SEED_PROP, sizeof(seedBuffer), (EFI_UINT8*) &seedBuffer);
934
935}
936}
937
938 // setup '/chosen/memory-map' node
939 Node * mapNode = DT__FindNode("/chosen/memory-map", false);
940if (mapNode == 0) {
941DBG("setupChosenNode:Couldn't get '/chosen/memory-map' node\n");
942} else { /*
943 static EFI_UINT64 BootClutPropValue = 0;
944 static EFI_UINT64 FailedBootPictPropValue = 0;
945 BootClutPropValue = ((EFI_UINT64)sizeof(appleClut8) << 32) | (EFI_UINT64)(EFI_UINT8 *)&appleClut8;
946 FailedBootPictPropValue = ((EFI_UINT64)(sizeof(gFailedBootPict) + 32) << 32) | (EFI_UINT64)(EFI_UINT8 *)&gFailedBootPict;
947 if (MacOSVerCurrent < MacOSVer2Int("10.7.3")) {
948 DT__AddProperty(node, "BootCLUT", sizeof(EFI_UINT64), (EFI_UINT64 *)&BootClutPropValue);
949 DT__AddProperty(node, "Pict-FailedBoot", sizeof(EFI_UINT64), (EFI_UINT64 *)&FailedBootPictPropValue);
950 } else {
951 DT__AddProperty(node, "FailedCLUT", sizeof(EFI_UINT64), (EFI_UINT64 *)&BootClutPropValue);
952 DT__AddProperty(node, "FailedImage", sizeof(EFI_UINT64), (EFI_UINT64 *)&FailedBootPictPropValue);
953 } */
954 }
955}
956
957/*
958 * Load the smbios.plist override config file if any
959 */
960static void setupSmbiosConfigFile(const char *filename)
961{
962chardirSpecSMBIOS[128];
963const char*override_pathname = NULL;
964intlen = 0, err = 0;
965extern void scan_mem();
966
967// Take in account user overriding
968if (getValueForKey(kSMBIOSKey, &override_pathname, &len, &bootInfo->chameleonConfig) && len > 0)
969{
970// Specify a path to a file, e.g. SMBIOS=/Extra/macProXY.plist
971sprintf(dirSpecSMBIOS, override_pathname);
972err = loadConfigFile(dirSpecSMBIOS, &bootInfo->smbiosConfig);
973}
974else
975{
976// Check selected volume's Extra.
977sprintf(dirSpecSMBIOS, "/Extra/%s", filename);
978if ( (err = loadConfigFile(dirSpecSMBIOS, &bootInfo->smbiosConfig)) )
979{
980// Check booter volume/rdbt Extra.
981sprintf(dirSpecSMBIOS, "bt(0,0)/Extra/%s", filename);
982err = loadConfigFile(dirSpecSMBIOS, &bootInfo->smbiosConfig);
983}
984}
985
986if (err)
987{
988DBG("setupSmbiosConfigFile: No SMBIOS replacement found.\n");
989}
990
991// get a chance to scan mem dynamically if user asks for it while having the config options
992// loaded as well, as opposed to when it was in scan_platform(); also load the orig. smbios
993// so that we can access dmi info, without patching the smbios yet.
994scan_mem();
995}
996
997void saveOriginalSMBIOS(void)
998{
999Node *node;
1000SMBEntryPoint *origeps;
1001void *tableAddress;
1002
1003node = DT__FindNode("/efi/platform", false);
1004if (!node)
1005{
1006DBG("saveOriginalSMBIOS: '/efi/platform' node not found\n");
1007return;
1008}
1009
1010origeps = getSmbios(SMBIOS_ORIGINAL);
1011if (!origeps)
1012{
1013 DBG("saveOriginalSMBIOS: original SMBIOS not found\n");
1014return;
1015}
1016
1017tableAddress = (void *)AllocateKernelMemory(origeps->dmi.tableLength);
1018if (!tableAddress)
1019{
1020 DBG("saveOriginalSMBIOS: can not allocate memory for original SMBIOS\n");
1021return;
1022}
1023
1024memcpy(tableAddress, (void *)origeps->dmi.tableAddress, origeps->dmi.tableLength);
1025DT__AddProperty(node, "SMBIOS", origeps->dmi.tableLength, tableAddress);
1026}
1027
1028char saveOriginalACPI()
1029{
1030 Node *node = DT__FindNode("/chosen/acpi", true);
1031 if (!node) {
1032 DBG("saveOriginalACPI: node '/chosen/acpi' not found. Can't save OEM ACPI tables.\n");
1033 return -1;
1034 }
1035
1036 struct acpi_2_rsdp *RSDP = getRSDPaddress();
1037
1038 if (!RSDP) {
1039 DBG("saveOriginalACPI: RSDP not found or incorrect, can't save OEM tables.\n");
1040 return -1;
1041 }
1042
1043 DBG("saveOriginalACPI: saving OEM tables into IODT/chosen/acpi...\n");
1044 uint32_t length = RSDP->Revision ? RSDP->Length : 20;
1045 uint8_t nameLen = strlen("RSDP@") + 8 + 1;
1046 char *nameBuf = malloc(nameLen);
1047 sprintf(nameBuf, "RSDP@%08X", RSDP);
1048 DBG("saveOriginalACPI: OEM table %s found, size=%d: saving.\n", nameBuf, length);
1049 DT__AddProperty(node, nameBuf, length, RSDP);
1050 uint8_t total_number = 1;
1051 uint32_t total_size = length;
1052 uint8_t r, ssdt_number = 0;
1053 struct acpi_2_header *RSDT = (struct acpi_2_header *)(RSDP->RsdtAddress), *XSDT = NULL;
1054 void *origTable = (void *)(RSDT + 1), *origTable2, *origTable3;
1055 if (RSDT && tableSign(RSDT->Signature, "RSDT")) {
1056 length = RSDT->Length;
1057 nameLen = strlen("RSDT@") + 8 + 1;
1058 nameBuf = malloc(nameLen);
1059 sprintf(nameBuf, "RSDT@%08X", RSDT);
1060 DBG("saveOriginalACPI: OEM table %s found, size=%d: saving.\n", nameBuf, length);
1061 DT__AddProperty(node, nameBuf, length, RSDT);
1062 total_size += length;
1063 total_number++;
1064 for (; origTable < ((void *)RSDT + RSDT->Length); origTable += 4) {
1065 origTable2 = (void *)(*(uint32_t *)origTable);
1066 length = ((struct acpi_2_header *)origTable2)->Length;
1067 total_size += length;
1068 total_number++;
1069 if (tableSign(((struct acpi_2_header *)origTable2)->Signature, "SSDT")) {
1070 ssdt_number++;
1071 if (!strcmp(((struct acpi_2_header *)origTable2)->OEMTableId, "CpuPm")) {
1072 nameLen = strlen("SSDT@") + 8 + 1;
1073 nameBuf = malloc(nameLen);
1074 sprintf(nameBuf, "SSDT@%08X", origTable2);
1075 DBG("saveOriginalACPI: OEM table %s found, size=%d: saving.\n", nameBuf, length);
1076 DT__AddProperty(node, nameBuf, length, origTable2);
1077 origTable2 += sizeof(struct acpi_2_header) + 15;
1078 r = *((uint8_t *)origTable2 - 2) / 3;
1079 for (; r > 0; r--, origTable2 += sizeof(struct ssdt_pmref)) {
1080 origTable3 = (void *)(((struct ssdt_pmref *)origTable2)->addr);
1081 if (!origTable3) continue;
1082 length = ((struct acpi_2_header *)origTable3)->Length;
1083 nameLen = strlen("SSDT_@") + strlen(((struct acpi_2_header *)origTable3)->OEMTableId) + 8 + 1;
1084 nameBuf = malloc(nameLen);
1085 sprintf(nameBuf, "SSDT_%s@%08X", ((struct acpi_2_header *)origTable3)->OEMTableId, origTable3);
1086 DBG("saveOriginalACPI: OEM table %s found, size=%d: saving.\n", nameBuf, length);
1087 DT__AddProperty(node, nameBuf, length, origTable3);
1088 total_size += length;
1089 total_number++;
1090 }
1091 } else {
1092 nameLen = strlen("SSDT-@") + ((ssdt_number < 10) ? 1:2) + 8 + 1;
1093 nameBuf = malloc(nameLen);
1094 sprintf(nameBuf, "SSDT-%d@%08X", ssdt_number, origTable2);
1095 DBG("saveOriginalACPI: OEM table %s found, size=%d: saving.\n", nameBuf, length);
1096 DT__AddProperty(node, nameBuf, length, origTable2);
1097 }
1098 } else {
1099 nameLen = strlen("XXXX@") + 8 + 1;
1100 nameBuf = malloc(nameLen);
1101 sprintf(nameBuf, "%c%c%c%c@%08X", ((char *)origTable2)[0], ((char *)origTable2)[1], ((char *)origTable2)[2], ((char *)origTable2)[3], origTable2);
1102 DBG("saveOriginalACPI: OEM table %s found, size=%d: saving.\n", nameBuf, length);
1103 DT__AddProperty(node, nameBuf, length, origTable2);
1104 if (tableSign(((struct acpi_2_header *)origTable2)->Signature, "FACP")) {
1105 origTable3 = (void *)(((struct acpi_2_fadt *)origTable2)->FACS);
1106 length = ((struct acpi_2_header *)origTable3)->Length;
1107 nameLen = strlen("FACS@") + 8 + 1;
1108 nameBuf = malloc(nameLen);
1109 sprintf(nameBuf, "FACS@%08X", origTable3);
1110 DBG("saveOriginalACPI: OEM table %s found, size=%d: saving.\n", nameBuf, length);
1111 DT__AddProperty(node, nameBuf, length, origTable3);
1112 total_size += length;
1113 total_number++;
1114 origTable3 = (void *)(((struct acpi_2_fadt *)origTable2)->DSDT);
1115 length = ((struct acpi_2_header *)origTable3)->Length;
1116 nameLen = strlen("DSDT@") + 8 + 1;
1117 nameBuf = malloc(nameLen);
1118 sprintf(nameBuf, "DSDT@%08X", origTable3);
1119 DBG("saveOriginalACPI: OEM table %s found, size=%d: saving.\n", nameBuf, length);
1120 DT__AddProperty(node, nameBuf, length, origTable3);
1121 total_size += length;
1122 total_number++;
1123 }
1124 }
1125 }
1126 } else {
1127 DBG("saveOriginalACPI: can't find OEM table: RSDT@%08x.\n", RSDT);
1128 }
1129
1130 if (RSDP->Revision > 0) {
1131 XSDT = (struct acpi_2_header *)(RSDP->XsdtAddress);
1132 if (XSDT && tableSign(XSDT->Signature, "XSDT")) {
1133 length = XSDT->Length;
1134 nameLen = strlen("XSDT@") + 8 + 1;
1135 nameBuf = malloc(nameLen);
1136 sprintf(nameBuf, "XSDT@%08X", XSDT);
1137 DBG("saveOriginalACPI: OEM table %s found, size=%d: saving.\n", nameBuf, length);
1138 DT__AddProperty(node, nameBuf, length, XSDT);
1139 total_number++;
1140 total_size += length;
1141 origTable = (void *)(XSDT + 1);
1142 for (r = 0; origTable < ((void *)XSDT + XSDT->Length); origTable += 8, r += 4) {
1143 if ((uint64_t)*(uint32_t *)((void *)(RSDT + 1) + r) != *(uint64_t *)origTable) {
1144 origTable2 = (void *)(*(uint64_t *)origTable);
1145 length = ((struct acpi_2_header *)origTable2)->Length;
1146 nameLen = strlen("X_XXXX@") + 8 + 1;
1147 nameBuf = malloc(nameLen);
1148 sprintf(nameBuf, "X_%c%c%c%c@%08X", ((char *)origTable2)[0], ((char *)origTable2)[1], ((char *)origTable2)[2], ((char *)origTable2)[3], origTable2);
1149 DBG("saveOriginalACPI: OEM table %s found, size=%d: saving.\n", nameBuf, length);
1150 DT__AddProperty(node, nameBuf, length, origTable2);
1151 total_size += length;
1152 total_number++;
1153 if (tableSign(((struct acpi_2_header *)origTable2)->Signature, "FACP")) {
1154 if (((struct acpi_2_fadt *)origTable2)->FACS != (uint32_t)((struct acpi_2_fadt *)origTable2)->X_FACS) {
1155 origTable3 = (void *)(((struct acpi_2_fadt *)origTable2)->X_FACS);
1156 length = ((struct acpi_2_rsdt *)origTable3)->Length;
1157 nameLen = strlen("X_FACS@") + 8 + 1;
1158 nameBuf = malloc(nameLen);
1159 sprintf(nameBuf, "X_FACS@%08X", origTable3);
1160 DBG("saveOriginalACPI: OEM table %s found, size=%d: saving.\n", nameBuf, length);
1161 DT__AddProperty(node, nameBuf, length, origTable3);
1162 total_size += length;
1163 total_number++;
1164 }
1165 if (((struct acpi_2_fadt *)origTable2)->DSDT != (uint32_t)((struct acpi_2_fadt *)origTable2)->X_DSDT) {
1166 origTable3 = (void *)(((struct acpi_2_fadt *)origTable2)->X_DSDT);
1167 length = ((struct acpi_2_rsdt *)origTable3)->Length;
1168 nameLen = strlen("X_DSDT@") + 8 + 1;
1169 nameBuf = malloc(nameLen);
1170 sprintf(nameBuf, "X_DSDT@%08X", origTable3);
1171 DBG("saveOriginalACPI: OEM table %s found, size=%d: saving.\n", nameBuf, length);
1172 DT__AddProperty(node, nameBuf, length, origTable3);
1173 total_size += length;
1174 total_number++;
1175 }
1176 }
1177 }
1178 }
1179 } else {
1180 DBG("saveOriginalACPI: can't find OEM table: XSDT@%x.\n", origTable);
1181 }
1182 }
1183
1184 DBG("saveOriginalACPI: %d original table%s found and saved, total size=%d.\n", total_number, (total_number != 1) ? "s" : "", total_size);
1185 if (!RSDT && !XSDT) return -1;
1186 else return total_number;
1187}
1188
1189/*
1190 * Entrypoint from boot.c
1191 */
1192void setupFakeEfi(void)
1193{
1194// Generate efi device strings
1195setup_pci_devs(root_pci_dev);
1196
1197readSMBIOSInfo(getSmbios(SMBIOS_ORIGINAL));
1198
1199// load smbios.plist file if any
1200setupSmbiosConfigFile("smbios.plist");
1201
1202 // Setup ACPI with DSDT overrides (mackerintel's patch)
1203setupAcpi();
1204
1205 setupSMBIOS();
1206
1207 // Setup board-id: need to be called after getSmbios!
1208 setupBoardId();
1209
1210 // Setup system-type: We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()
1211// because we need to take care of FACP original content, if it is correct.
1212setupSystemType();
1213
1214 // Setup the '/' node
1215//setupRootNode();
1216
1217// Setup the '/chosen' node
1218setupChosenNode();
1219
1220// Initialize the base table
1221if (archCpuType == CPU_TYPE_I386)
1222{
1223setupEfiTables32();
1224}
1225else
1226{
1227setupEfiTables64();
1228}
1229
1230 // Setup efi node
1231setupEfiNode();
1232
1233 saveOriginalSMBIOS();
1234
1235 saveOriginalACPI();
1236}
1237

Archive Download this file

Revision: 2469