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

Archive Download this file

Revision: HEAD