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
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*/
473static EFI_UINT8 RANDOM_SEED_PROP_VALUE[64];
474
475/*
476 * Get an smbios option string option to convert to EFI_CHAR16 string
477 */
478static EFI_CHAR16* getSmbiosChar16(const char * key, size_t* len)
479{
480const char*src = getStringForKey(key, &bootInfo->smbiosConfig);
481EFI_CHAR16* dst = 0;
482size_t i = 0;
483
484if (!key || !(*key) || !len || !src)
485{
486return 0;
487}
488
489*len = strlen(src);
490dst = (EFI_CHAR16*) malloc( ((*len)+1) * 2 );
491for (; i < (*len); i++)
492{
493dst[i] = src[i];
494}
495dst[(*len)] = '\0';
496*len = ((*len)+1)*2; // return the CHAR16 bufsize including zero terminated CHAR16
497return dst;
498}
499
500// Bungo
501/*
502 * Get the SystemID from the bios dmi info
503
504staticEFI_CHAR8* getSmbiosUUID()
505{
506static EFI_CHAR8 uuid[UUID_LEN];
507int i, isZero, isOnes;
508SMBByte*p;
509
510p = (SMBByte*)Platform.UUID;
511
512for (i=0, isZero=1, isOnes=1; i<UUID_LEN; i++)
513{
514if (p[i] != 0x00)
515{
516isZero = 0;
517}
518
519if (p[i] != 0xff)
520{
521isOnes = 0;
522}
523}
524
525if (isZero || isOnes) // empty or setable means: no uuid present
526{
527verbose("No UUID present in SMBIOS System Information Table\n");
528return 0;
529}
530
531memcpy(uuid, p, UUID_LEN);
532return uuid;
533}
534
535
536// return a binary UUID value from the overriden SystemID and SMUUID if found,
537// or from the bios if not, or from a fixed value if no bios value is found
538
539static EFI_CHAR8* getSystemID()
540{
541// unable to determine UUID for host. Error: 35 fix
542// Rek: new SMsystemid option conforming to smbios notation standards, this option should
543// belong to smbios config only ...
544const char *sysId = getStringForKey(kSystemID, &bootInfo->chameleonConfig);
545EFI_CHAR8*ret = getUUIDFromString(sysId);
546
547if (!sysId || !ret) // try bios dmi info UUID extraction
548{
549ret = getSmbiosUUID();
550sysId = 0;
551}
552
553if (!ret)
554{
555// no bios dmi UUID available, set a fixed value for system-id
556ret=getUUIDFromString((sysId = (const char*) SYSTEM_ID));
557}
558verbose("Customizing SystemID with : %s\n", getStringFromUUID(ret)); // apply a nice formatting to the displayed output
559return ret;
560}
561 */
562
563/*
564 * Must be called AFTER setupAcpi because we need to take care of correct
565 * FACP content to reflect in ioregs
566 */
567void setupSystemType()
568{
569Node *node = DT__FindNode("/", false);
570if (node == 0)
571{
572stop("Couldn't get root '/' node");
573}
574// we need to write this property after facp parsing
575// Export system-type only if it has been overrriden by the SystemType option
576DT__AddProperty(node, SYSTEM_TYPE_PROP, sizeof(Platform.Type), &Platform.Type);
577}
578
579bool getKernelCompat(EFI_UINT8 *compat)
580{
581 int kernelFileRef;
582 EFI_UINT8 readBytes;
583 char kernelFilePath[512], kernelHeaderBuf[sizeof(struct fat_header) + 4*sizeof(struct fat_arch)];
584
585 //strlcpy(kernelFilePath, bootInfo->bootFile, sizeof(kernelFilePath)); // user defined path
586 snprintf(kernelFilePath, sizeof(kernelFilePath), "%s", bootInfo->bootFile); // user defined path
587 if ((kernelFileRef = open(kernelFilePath, 0)) >= 0) {
588 } else {
589 snprintf(kernelFilePath, sizeof(kernelFilePath), "/%s", bootInfo->bootFile); // append a leading '/'
590 if ((kernelFileRef = open(kernelFilePath, 0)) >= 0) {
591 } else {
592 snprintf(kernelFilePath, sizeof(kernelFilePath), "/System/Library/Kernels/%s", bootInfo->bootFile); // Yosemite path
593 if ((kernelFileRef = open(kernelFilePath, 0)) >= 0) {
594 } else {
595 verbose("EfiKernelCompat: can't find any kernel file!\n");
596 return false;
597 }
598 }
599 }
600
601 verbose("EfiKernelCompat: reading kernel header from file: %s ... ", kernelFilePath);
602 if ((readBytes = read(kernelFileRef, kernelHeaderBuf, sizeof(struct fat_header) + 4*sizeof(struct fat_arch))) > 0) {
603 verbose("OK, read %d bytes.\n", readBytes);
604 } else {
605 verbose("EROR, can't read kernel file!\n");
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 verbose("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 verbose(" i386");
627 break;
628 case CPU_TYPE_X86_64:
629 verbose(" x86_64");
630 break;
631 case CPU_TYPE_POWERPC:
632 verbose(" PPC");
633 break;
634 case CPU_TYPE_POWERPC64:
635 verbose(" PPC64");
636 break;
637 default:
638 verbose(" 0x%x", fatArchPtr->cputype);
639 }
640 if (fatHeaderPtr->nfat_arch - 1 > 0) verbose(" | ");
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 verbose(" ]\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 verbose("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 verbose("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 verbose("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 verbose("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 verbose("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 == NULL)
834{
835stop("setupChosenNode: Couldn't get '/chosen' node");
836}
837
838int length = strlen(gBootUUIDString);
839if (length)
840{
841DT__AddProperty(chosenNode, "boot-uuid", length + 1, gBootUUIDString);
842}
843
844length = strlen(bootArgs->CommandLine);
845DT__AddProperty(chosenNode, "boot-args", length + 1, bootArgs->CommandLine);
846
847length = strlen(bootInfo->bootFile);
848 if (length) {
849 DT__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
856DT__AddProperty(chosenNode, MACHINE_SIG_PROP, sizeof(EFI_UINT32), (EFI_UINT32 *)&Platform.HWSignature);
857
858 // add if Yosemite or better only
859 if (MacOSVerCurrent >= MacOSVer2Int("10.10"))
860 {
861 //DT__AddProperty(node, RANDOM_SEED_PROP, sizeof(RANDOM_SEED_PROP_VALUE), (EFI_UINT8 *)&RANDOM_SEED_PROP_VALUE);
862
863 //
864 // Pike R. Alpha - 12 October 2014
865 //
866 UInt8 index = 0;
867 EFI_UINT16 PMTimerValue = 0;
868 EFI_UINT32 randomValue, tempValue, cpuTick;
869 EFI_UINT32 ecx, esi, edi;
870 EFI_UINT32 rcx, rdx, rsi, rdi;
871
872 EFI_UINT32 *seedPtr = (EFI_UINT32 *)RANDOM_SEED_PROP_VALUE;
873 randomValue = tempValue = ecx = esi = edi = 0;// xor%ecx,%ecx
874 cpuTick = rcx = rdx = rsi = rdi = 0;
875
876 // LEAF_1 - Feature Information (Function 01h).
877 if (Platform.CPU.CPUID[CPUID_1][2] & 0x40000000)// Checking ecx:bit-30
878 {
879 //
880 // i5/i7 Ivy Bridge and Haswell processors with RDRAND support.
881 //
882 //EFI_UINT32 seedBuffer[16] = {0};
883 //
884 // Main loop to get 16 qwords (four bytes each).
885 //
886 for (index = 0; index < 16; index++)// 0x17e12:
887 {
888 randomValue = computeRand();// callq0x18e20
889 cpuTick = getCPUTick();// callq0x121a7
890 randomValue = (randomValue ^ cpuTick);// xor%rdi,%rax
891 seedPtr[index] = randomValue;// mov%rax,(%r15,%rsi,8)
892 }// jb0x17e12
893 }
894 else
895 {
896 //
897 // All other processors without RDRAND support.
898 //
899 //EFI_UINT8 seedBuffer[64] = {0};
900 //
901 // Main loop to get the 64 bytes.
902 //
903 do// 0x17e55:
904 {
905 PMTimerValue = inw(0x408);// in(%dx),%ax
906 esi = PMTimerValue;// movzwl%ax,%esi
907
908 if (esi < ecx)// cmp%ecx,%esi
909 {
910 continue;// jb0x17e55(retry)
911 }
912
913 cpuTick = getCPUTick();// callq0x121a7
914 rcx = (cpuTick >> 8);// mov%rax,%rcx
915 // shr$0x8,%rcx
916 rdx = (cpuTick >> 10);// mov%rax,%rdx
917 // shr$0x10,%rdx
918 rdi = rsi;// mov%rsi,%rdi
919 rdi = (rdi ^ cpuTick);// xor%rax,%rdi
920 rdi = (rdi ^ rcx);// xor%rcx,%rdi
921 rdi = (rdi ^ rdx);// xor%rdx,%rdi
922
923 RANDOM_SEED_PROP_VALUE[index] = (rdi & 0xff);// mov%dil,(%r15,%r12,1)
924
925 edi = (edi & 0x2f);// and$0x2f,%edi
926 edi = (edi + esi);// add%esi,%edi
927 index++;// incr12
928 ecx = (edi & 0xffff);// movzwl%di,%ecx
929
930 } while (index < 64);// cmp%r14d,%r12d
931 // jne0x17e55(next)
932 }
933 DT__AddProperty(chosenNode, "random-seed", sizeof(RANDOM_SEED_PROP_VALUE), (EFI_UINT8 *)&RANDOM_SEED_PROP_VALUE);
934 }
935
936 // setup '/chosen/memory-map' node
937 Node *memoryMapNode = DT__FindNode("/chosen/memory-map", false);
938if (memoryMapNode == NULL)
939{
940verbose("setupChosenNode:Couldn't get '/chosen/memory-map' node\n");
941} else { /*
942 static EFI_UINT64 BootClutPropValue = 0;
943 static EFI_UINT64 FailedBootPictPropValue = 0;
944 BootClutPropValue = ((EFI_UINT64)sizeof(appleClut8) << 32) | (EFI_UINT64)(EFI_UINT8 *)&appleClut8;
945 FailedBootPictPropValue = ((EFI_UINT64)(sizeof(gFailedBootPict) + 32) << 32) | (EFI_UINT64)(EFI_UINT8 *)&gFailedBootPict;
946 if (MacOSVerCurrent < MacOSVer2Int("10.7.3")) {
947 DT__AddProperty(node, "BootCLUT", sizeof(EFI_UINT64), (EFI_UINT64 *)&BootClutPropValue);
948 DT__AddProperty(node, "Pict-FailedBoot", sizeof(EFI_UINT64), (EFI_UINT64 *)&FailedBootPictPropValue);
949 } else {
950 DT__AddProperty(node, "FailedCLUT", sizeof(EFI_UINT64), (EFI_UINT64 *)&BootClutPropValue);
951 DT__AddProperty(node, "FailedImage", sizeof(EFI_UINT64), (EFI_UINT64 *)&FailedBootPictPropValue);
952 } */
953 }
954}
955
956/*
957 * Load the smbios.plist override config file if any
958 */
959static void setupSmbiosConfigFile(const char *filename)
960{
961chardirSpecSMBIOS[128];
962const char*override_pathname = NULL;
963intlen = 0, err = 0;
964extern void scan_mem();
965
966// Take in account user overriding
967if (getValueForKey(kSMBIOSKey, &override_pathname, &len, &bootInfo->chameleonConfig) && len > 0)
968{
969// Specify a path to a file, e.g. SMBIOS=/Extra/macProXY.plist
970sprintf(dirSpecSMBIOS, override_pathname);
971err = loadConfigFile(dirSpecSMBIOS, &bootInfo->smbiosConfig);
972}
973else
974{
975// Check selected volume's Extra.
976sprintf(dirSpecSMBIOS, "/Extra/%s", filename);
977if ( (err = loadConfigFile(dirSpecSMBIOS, &bootInfo->smbiosConfig)) )
978{
979// Check booter volume/rdbt Extra.
980sprintf(dirSpecSMBIOS, "bt(0,0)/Extra/%s", filename);
981err = loadConfigFile(dirSpecSMBIOS, &bootInfo->smbiosConfig);
982}
983}
984
985if (err)
986{
987verbose("setupSmbiosConfigFile: No SMBIOS replacement found.\n");
988}
989
990// get a chance to scan mem dynamically if user asks for it while having the config options
991// loaded as well, as opposed to when it was in scan_platform(); also load the orig. smbios
992// so that we can access dmi info, without patching the smbios yet.
993scan_mem();
994}
995
996void saveOriginalSMBIOS(void)
997{
998Node *node;
999SMBEntryPoint *origeps;
1000void *tableAddress;
1001
1002node = DT__FindNode("/efi/platform", false);
1003if (!node)
1004{
1005verbose("saveOriginalSMBIOS: '/efi/platform' node not found\n");
1006return;
1007}
1008
1009origeps = getSmbios(SMBIOS_ORIGINAL);
1010if (!origeps)
1011{
1012 verbose("saveOriginalSMBIOS: original SMBIOS not found\n");
1013return;
1014}
1015
1016tableAddress = (void *)AllocateKernelMemory(origeps->dmi.tableLength);
1017if (!tableAddress)
1018{
1019 verbose("saveOriginalSMBIOS: can not allocate memory for original SMBIOS\n");
1020return;
1021}
1022
1023memcpy(tableAddress, (void *)origeps->dmi.tableAddress, origeps->dmi.tableLength);
1024DT__AddProperty(node, "SMBIOS", origeps->dmi.tableLength, tableAddress);
1025}
1026
1027char saveOriginalACPI()
1028{
1029 verbose("\nsaveOriginalACPI: Saving OEM tables into IODT:/chosen/acpi...\n");
1030
1031 Node *node = DT__FindNode("/chosen/acpi", true);
1032 if (!node) {
1033 verbose("saveOriginalACPI: node '/chosen/acpi' not found, can't save any OEM tables.\n\n");
1034 return 0;
1035 }
1036
1037 struct acpi_2_rsdp *RSDP = getRSDPaddress();
1038
1039 if (!RSDP) {
1040 verbose("saveOriginalACPI: OEM RSDP not found or incorrect, can't save any OEM tables.\n\n");
1041 return 0;
1042 }
1043
1044 uint8_t r,
1045 total_number = 1,
1046 ssdt_number = 0,
1047 nameLen = strlen("XXXX@XXXXXXXX");
1048 uint32_t length = RSDP->Revision ? RSDP->Length : 20;
1049 char *nameBuf = malloc(nameLen);
1050
1051 sprintf(nameBuf, "RSDP@%08X", (uint32_t)RSDP);
1052 verbose("saveOriginalACPI: OEM table %s found, length=%d: saving.\n", nameBuf, length);
1053 DT__AddProperty(node, nameBuf, length, RSDP);
1054 uint32_t total_length = length;
1055
1056 struct acpi_2_header *RSDT = (struct acpi_2_header *)(RSDP->RsdtAddress),
1057 *XSDT = (struct acpi_2_header *)(uint32_t)(RSDP->XsdtAddress);
1058
1059 void *origTable = NULL,
1060 *origTable2 = NULL,
1061 *origTable3 = NULL,
1062 *origTable4 = NULL;
1063
1064 if ((RSDP->RsdtAddress > 0) && (RSDP->RsdtAddress < 0xFFFFFFFF) && tableSign(RSDT->Signature, "RSDT")) {
1065 origTable = (void *)(RSDT + 1);
1066 nameBuf = malloc(nameLen + 1);
1067 sprintf(nameBuf, "RSDT@%08X", (uint32_t)RSDT);
1068 verbose("saveOriginalACPI: OEM table %s found, lenght=%d: saving.\n", nameBuf, RSDT->Length);
1069 DT__AddProperty(node, nameBuf, RSDT->Length, RSDT);
1070 total_length += RSDT->Length;
1071 total_number++;
1072 for ( ; origTable < ((void *)RSDT + RSDT->Length); origTable += 4) {
1073 origTable2 = (void *)(*(uint32_t *)origTable);
1074 length = ((struct acpi_2_header *)origTable2)->Length;
1075 total_length += length;
1076 total_number++;
1077 if (tableSign(((struct acpi_2_header *)origTable2)->Signature, "SSDT")) {
1078 ssdt_number++;
1079 if (strcmp(((struct acpi_2_header *)origTable2)->OEMTableId, "CpuPm") == 0) {
1080 nameLen = strlen("SSDT@XXXXXXXX");
1081 nameBuf = malloc(nameLen + 1);
1082 sprintf(nameBuf, "SSDT@%08X", (uint32_t)origTable2);
1083 verbose("saveOriginalACPI: OEM table %s found, lenght=%d: saving.\n", nameBuf, length);
1084 DT__AddProperty(node, nameBuf, length, origTable2);
1085 origTable2 += sizeof(struct acpi_2_header) + 15;
1086 r = *((uint8_t *)origTable2 - 2) / 3; // e.g: Name (SSDT, Package (0x0C) -> 0x0C / 3 = 4 is number of sub SSDTs
1087 for (; r > 0; r--, origTable2 += sizeof(struct ssdt_pmref)) {
1088 origTable3 = (void *)(((struct ssdt_pmref *)origTable2)->addr);
1089 if (!((uint32_t)origTable3 > 0) && !((uint32_t)origTable3 < 0xFFFFFFFF)) continue; // incorrect, dropping
1090 length = ((struct acpi_2_header *)origTable3)->Length;
1091 nameLen = strlen("SSDT_@XXXXXXXX") + strlen((char *)((struct acpi_2_header *)origTable3)->OEMTableId);
1092 nameBuf = malloc(nameLen + 1);
1093 sprintf(nameBuf, "SSDT_%s@%08X", (char *)((struct acpi_2_header *)origTable3)->OEMTableId, (uint32_t)origTable3);
1094 verbose("saveOriginalACPI: OEM table %s found, lenght=%d: saving.\n", nameBuf, length);
1095 DT__AddProperty(node, nameBuf, length, origTable3);
1096 total_length += length;
1097 total_number++;
1098 }
1099 } else {
1100 nameLen = strlen("SSDT-@XXXXXXXX") + ((ssdt_number < 10)? 1:2);
1101 nameBuf = malloc(nameLen + 1);
1102 sprintf(nameBuf, "SSDT-%d@%08X", ssdt_number, (uint32_t)origTable2);
1103 verbose("saveOriginalACPI: OEM table %s found, lenght=%d: saving.\n", nameBuf, length);
1104 DT__AddProperty(node, nameBuf, length, origTable2);
1105 }
1106 } else {
1107 nameLen = strlen("XXXX@XXXXXXXX");
1108 nameBuf = malloc(nameLen + 1);
1109 sprintf(nameBuf, "%c%c%c%c@%08X", ((char *)origTable2)[0], ((char *)origTable2)[1], ((char *)origTable2)[2], ((char *)origTable2)[3], (uint32_t)origTable2);
1110 verbose("saveOriginalACPI: OEM table %s found, lenght=%d: saving.\n", nameBuf, length);
1111 DT__AddProperty(node, nameBuf, length, origTable2);
1112 if (tableSign(((struct acpi_2_header *)origTable2)->Signature, "FACP")) {
1113 origTable3 = (void *)(((struct acpi_2_fadt *)origTable2)->FACS);
1114 length = ((struct acpi_2_header *)origTable3)->Length;
1115 nameLen = strlen("FACS@XXXXXXXX");
1116 nameBuf = malloc(nameLen + 1);
1117 sprintf(nameBuf, "FACS@%08X", (uint32_t)origTable3);
1118 verbose("saveOriginalACPI: OEM table %s found, lenght=%d: saving.\n", nameBuf, length);
1119 DT__AddProperty(node, nameBuf, length, origTable3);
1120 total_length += length;
1121 total_number++;
1122 origTable3 = (void *)(((struct acpi_2_fadt *)origTable2)->DSDT);
1123 length = ((struct acpi_2_header *)origTable3)->Length;
1124 nameLen = strlen("DSDT@XXXXXXXX");
1125 nameBuf = malloc(nameLen + 1);
1126 sprintf(nameBuf, "DSDT@%08X", (uint32_t)origTable3);
1127 verbose("saveOriginalACPI: OEM table %s found, lenght=%d: saving.\n", nameBuf, length);
1128 DT__AddProperty(node, nameBuf, length, origTable3);
1129 total_length += length;
1130 total_number++;
1131 }
1132 }
1133 }
1134 } else {
1135 verbose("saveOriginalACPI: OEM table RSDT@%08x not found or incorrect.\n", RSDP->RsdtAddress);
1136 }
1137 if (gVerboseMode) pause("");
1138
1139 if (RSDP->Revision > 0) {
1140 verbose("\n");
1141 if ((RSDP->XsdtAddress > 0) && (RSDP->XsdtAddress < 0xFFFFFFFF) && tableSign(XSDT->Signature, "XSDT")) {
1142 verbose("saveOriginalACPI: OEM table XSDT@%016X found, lenght=%d: saving.\n", (uint32_t)XSDT, XSDT->Length);
1143 nameLen = strlen("XSDT@XXXXXXXX");
1144 nameBuf = malloc(nameLen + 1);
1145 sprintf(nameBuf, "XSDT@%08X", (uint32_t)XSDT);
1146 DT__AddProperty(node, nameBuf, XSDT->Length, XSDT);
1147 total_number++;
1148 total_length += XSDT->Length;
1149 for (origTable = (void *)(RSDT + 1), origTable4 = (void *)(XSDT + 1); origTable4 < ((void *)XSDT + XSDT->Length); origTable += 4, origTable4 += 8) {
1150 origTable2 = (void *)(uint32_t)(*(uint64_t *)origTable4);
1151 length = ((struct acpi_2_header *)origTable2)->Length;
1152 verbose("saveOriginalACPI: OEM table X_%c%c%c%c@%016X found, lenght=%d: ", ((char *)origTable2)[0], ((char *)origTable2)[1], ((char *)origTable2)[2], ((char *)origTable2)[3], (uint32_t)origTable2, length);
1153 if (*(uint32_t *)origTable != (uint32_t)origTable2) { // already saved?
1154 verbose("saving.\n");
1155 nameLen = strlen("X_XXXX@XXXXXXXX");
1156 nameBuf = malloc(nameLen + 1);
1157 sprintf(nameBuf, "X_%c%c%c%c@%08X", ((char *)origTable2)[0], ((char *)origTable2)[1], ((char *)origTable2)[2], ((char *)origTable2)[3], (uint32_t)origTable2);
1158 DT__AddProperty(node, nameBuf, length, origTable2);
1159 total_length += length;
1160 total_number++;
1161
1162 if (tableSign(((struct acpi_2_header *)origTable2)->Signature, "SSDT") && (strcmp(((struct acpi_2_header *)origTable2)->OEMTableId, "CpuPm") == 0)) {
1163 // Get rest of ssdts from ssdt_pmref
1164 r = *((uint8_t *)origTable2 - 2) / 3; // e.g: Name (SSDT, Package (0x0C) -> 0x0C / 3 = 4 is number of sub SSDTs
1165 for (; r > 0; r--, origTable2 += sizeof(struct ssdt_pmref)) {
1166 origTable3 = (void *)(((struct ssdt_pmref *)origTable2)->addr);
1167 if (!((uint32_t)origTable3 > 0) && !((uint32_t)origTable3 < 0xFFFFFFFF)) continue; // incorrect, dropping
1168 length = ((struct acpi_2_header *)origTable3)->Length;
1169 nameLen = strlen("SSDT_@XXXXXXXX") + strlen((char *)((struct acpi_2_header *)origTable3)->OEMTableId);
1170 nameBuf = malloc(nameLen + 1);
1171 sprintf(nameBuf, "SSDT_%s@%08X", (char *)((struct acpi_2_header *)origTable3)->OEMTableId, (uint32_t)origTable3);
1172 verbose("saveOriginalACPI: OEM table %s found, lenght=%d: saving.\n", nameBuf, length);
1173 DT__AddProperty(node, nameBuf, length, origTable3);
1174 total_length += length;
1175 total_number++;
1176 }
1177 continue;
1178 }
1179
1180 if (tableSign(((struct acpi_2_header *)origTable2)->Signature, "FACP")) {
1181 origTable3 = (void *)(((struct acpi_2_fadt *)origTable2)->X_FACS); // take x_facs assuming facs (from x_facp) should be equal to it
1182 length = ((struct acpi_2_rsdt *)origTable3)->Length;
1183 verbose("saveOriginalACPI: OEM table X_FACS@%016X found, lenght=%d: ", (uint32_t)origTable3, length);
1184 if (origTable3 != (void *)(((struct acpi_2_fadt *)origTable2)->FACS)) {
1185 verbose("saving.\n");
1186 nameLen = strlen("X_FACS@XXXXXXXX");
1187 nameBuf = malloc(nameLen + 1);
1188 sprintf(nameBuf, "X_FACS@%08X", (uint32_t)origTable3);
1189 DT__AddProperty(node, nameBuf, length, origTable3);
1190 total_length += length;
1191 total_number++;
1192 } else {
1193 verbose("already saved.\n");
1194 }
1195 // assuming only one dsdt in system, so x_facp should contain pointer to it same as facp
1196 origTable3 = (void *)(((struct acpi_2_fadt *)origTable2)->X_DSDT);
1197 length = ((struct acpi_2_rsdt *)origTable3)->Length;
1198 verbose("saveOriginalACPI: OEM table X_DSDT@%016X found, lenght=%d: ", origTable3, length);
1199 if (origTable3 != (void *)(((struct acpi_2_fadt *)origTable2)->DSDT)) {
1200 verbose("saving.\n");
1201 nameLen = strlen("X_DSDT@XXXXXXXX");
1202 nameBuf = malloc(nameLen + 1);
1203 sprintf(nameBuf, "X_DSDT@%08X", origTable3);
1204 DT__AddProperty(node, nameBuf, length, origTable3);
1205 total_length += length;
1206 total_number++;
1207 } else {
1208 verbose("already saved.\n");
1209 }
1210 continue;
1211 }
1212 } else {
1213 verbose("already saved.\n");
1214 }
1215 }
1216 } else {
1217 verbose("saveOriginalACPI: OEM table XSDT@%08X%08X not found or incorrect.\n", (uint32_t)(RSDP->XsdtAddress >> 32), (uint32_t)(RSDP->XsdtAddress & 0xFFFFFFFF));
1218 }
1219 }
1220
1221 if (!RSDT && !XSDT) {
1222 verbose("saveOriginalACPI: OEM RSDT & XSDT not found or incorrect, can't save any tables.\n\n");
1223 return 0;
1224 }
1225
1226 verbose("saveOriginalACPI: %d OEM table%s found and saved, total lenght=%d.\n\n", total_number, (total_number != 1) ? "s" : "", total_length);
1227 if (gVerboseMode) pause("");
1228
1229 return total_number;
1230}
1231
1232/*
1233 * Entrypoint from boot.c
1234 */
1235void setupFakeEfi(void)
1236{
1237// Generate efi device strings
1238setup_pci_devs(root_pci_dev);
1239
1240readSMBIOSInfo(getSmbios(SMBIOS_ORIGINAL));
1241
1242// load smbios.plist file if any
1243setupSmbiosConfigFile("smbios.plist");
1244
1245 // Setup ACPI with DSDT overrides (mackerintel's patch)
1246setupAcpi();
1247
1248 setupSMBIOS();
1249
1250 // Setup board-id: need to be called after getSmbios!
1251 setupBoardId();
1252
1253 // Setup system-type: We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()
1254// because we need to take care of FACP original content, if it is correct.
1255setupSystemType();
1256
1257 // Setup the '/' node
1258//setupRootNode();
1259
1260// Setup the '/chosen' node
1261setupChosenNode();
1262
1263// Initialize the base table
1264if (archCpuType == CPU_TYPE_I386)
1265{
1266setupEfiTables32();
1267}
1268else
1269{
1270setupEfiTables64();
1271}
1272
1273 // Setup efi node
1274setupEfiNode();
1275
1276 saveOriginalSMBIOS();
1277
1278 saveOriginalACPI();
1279}
1280

Archive Download this file

Revision: 2531