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
171 i++;
172
173 if (archCpuType == CPU_TYPE_I386)
174 {
175 gST32->NumberOfTableEntries = i;
176 }
177 else
178 {
179 gST64->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";
463static 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{
584 int kernelFileRef;
585 EFI_UINT8 readBytes;
586 char kernelFilePath[512], kernelHeaderBuf[sizeof(struct fat_header) + 4*sizeof(struct fat_arch)];
587
588 //strlcpy(kernelFilePath, bootInfo->bootFile, sizeof(kernelFilePath)); // user defined path
589 snprintf(kernelFilePath, sizeof(kernelFilePath), "%s", bootInfo->bootFile); // user defined path
590if ((kernelFileRef = open(kernelFilePath, 0)) >= 0)
591{
592}
593else
594{
595 snprintf(kernelFilePath, sizeof(kernelFilePath), "/%s", bootInfo->bootFile); // append a leading '/'
596if ((kernelFileRef = open(kernelFilePath, 0)) >= 0)
597{
598}
599else
600{
601 snprintf(kernelFilePath, sizeof(kernelFilePath), "/System/Library/Kernels/%s", bootInfo->bootFile); // Yosemite path
602if ((kernelFileRef = open(kernelFilePath, 0)) >= 0)
603{
604}
605else
606{
607 verbose("EfiKernelCompat: can't find any kernel file!\n");
608 return false;
609 }
610 }
611 }
612
613 verbose("EfiKernelCompat: reading kernel header from file: %s ... ", kernelFilePath);
614 if ((readBytes = read(kernelFileRef, kernelHeaderBuf, sizeof(struct fat_header) + 4*sizeof(struct fat_arch))) > 0) {
615 verbose("OK, read %d bytes.\n", readBytes);
616}
617else
618{
619 verbose("EROR, can't read kernel file!\n");
620 return false;
621 }
622
623 struct fat_header *fatHeaderPtr = (struct fat_header *)kernelHeaderBuf;
624struct fat_arch *fatArchPtr = (struct fat_arch *)(kernelHeaderBuf + sizeof(struct fat_header));
625 struct mach_header *thinHeaderPtr = (struct mach_header *)kernelHeaderBuf;
626 bool swapit = false;
627
628switch (fatHeaderPtr->magic)
629{
630 case FAT_CIGAM:
631 swapit = true;
632 fatHeaderPtr->nfat_arch = OSSwapInt32(fatHeaderPtr->nfat_arch);
633 case FAT_MAGIC:
634 *compat = 0;
635 verbose("EfiKernelCompat: kernel file is a fat binary: %d archs compatibility [", fatHeaderPtr->nfat_arch);
636 if (fatHeaderPtr->nfat_arch > 4) fatHeaderPtr->nfat_arch = 4;
637 for (; fatHeaderPtr->nfat_arch > 0; fatHeaderPtr->nfat_arch--, fatArchPtr++) {
638 if (swapit) fatArchPtr->cputype = OSSwapInt32(fatArchPtr->cputype);
639 switch(fatArchPtr->cputype) {
640 case CPU_TYPE_I386:
641 verbose(" i386");
642 break;
643 case CPU_TYPE_X86_64:
644 verbose(" x86_64");
645 break;
646 case CPU_TYPE_POWERPC:
647 verbose(" PPC");
648 break;
649 case CPU_TYPE_POWERPC64:
650 verbose(" PPC64");
651 break;
652 default:
653 verbose(" 0x%x", fatArchPtr->cputype);
654 }
655 if (fatHeaderPtr->nfat_arch - 1 > 0) verbose(" | ");
656 *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);
657 }
658 verbose(" ]\n");
659 break;
660 case MH_CIGAM:
661 case MH_CIGAM_64:
662 thinHeaderPtr->cputype = OSSwapInt32(thinHeaderPtr->cputype);
663 case MH_MAGIC:
664 case MH_MAGIC_64:
665 *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);
666 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"));
667 break;
668 default:
669 verbose("EfiKernelCompat: unknown kernel file '%s'. Can't determine arch compatibility!\n", kernelFilePath);
670 return false;
671 }
672
673 return true;
674}
675
676/*
677 * Installs all the needed configuration table entries
678 */
679static void setupEfiConfigurationTable()
680{
681// smbios_p = (EFI_PTR32)getSmbios(SMBIOS_PATCHED);
682if (smbios_p) {
683 if (EFI_SUCCESS == addConfigurationTable(&gEfiSmbiosTableGuid, &smbios_p, NULL)) {
684 verbose("Fake EFI: sucesfuly added %sbit configuration table for SMBIOS: guid {EB9D2D31-2D88-11D3-9A16-0090273FC14D}.\n", (archCpuType == CPU_TYPE_I386) ? "32":"64");
685 }
686 }
687
688// Setup ACPI with DSDT overrides (mackerintel's patch)
689//setupAcpi();
690
691 if (acpi10_p) {
692 if (EFI_SUCCESS == addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI")) {
693 verbose("Fake EFI: sucesfuly added %sbit configuration table for ACPI: guid {EB9D2D30-2D88-11D3-9A16-0090273FC14D}.\n", (archCpuType == CPU_TYPE_I386) ? "32":"64");
694 }
695 }
696 if (acpi20_p) {
697 if (EFI_SUCCESS == addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20")) {
698 verbose("Fake EFI: sucesfuly added %sbit configuration table for ACPI_20: guid {8868E871-E4F1-11D3-BC22-0080C73C8881}.\n", (archCpuType == CPU_TYPE_I386) ? "32":"64");
699 }
700 }
701
702// We've obviously changed the count.. so fix up the CRC32
703if (archCpuType == CPU_TYPE_I386)
704{
705gST32->Hdr.CRC32 = 0;
706gST32->Hdr.CRC32 = crc32(0L, gST32, gST32->Hdr.HeaderSize);
707}
708else
709{
710gST64->Hdr.CRC32 = 0;
711gST64->Hdr.CRC32 = crc32(0L, gST64, gST64->Hdr.HeaderSize);
712}
713}
714
715void setupEfiNode(void)
716{
717EFI_CHAR16* ret16 = 0;
718size_t len = 0;
719
720Node *efiNode = DT__FindNode("/efi", true);
721 if (efiNode == 0)
722{
723stop("Couldn't get '/efi' node");
724}
725
726/* Bungo: we have 64 bit ability fake efi but mode may be changed 32/64, like in Macs
727if (archCpuType == CPU_TYPE_I386) {
728DT__AddProperty(efiNode, FIRMWARE_ABI_PROP, sizeof(FIRMWARE_ABI_32_PROP_VALUE), (EFI_CHAR8 *)FIRMWARE_ABI_32_PROP_VALUE);
729} else { */
730DT__AddProperty(efiNode, FIRMWARE_ABI_PROP, sizeof(FIRMWARE_ABI_64_PROP_VALUE), (EFI_CHAR8 *)FIRMWARE_ABI_64_PROP_VALUE);
731//}
732// So, added 'efi-mode' property to tell us what mode we use 32 or 64 bit
733DT__AddProperty(efiNode, EFI_MODE_PROP, sizeof(EFI_UINT8), (EFI_UINT8 *)&bootArgs->efiMode);
734
735DT__AddProperty(efiNode, FIRMWARE_REVISION_PROP, sizeof(FIRMWARE_REVISION), (EFI_UINT32 *)&FIRMWARE_REVISION);
736DT__AddProperty(efiNode, FIRMWARE_VENDOR_PROP, sizeof(FIRMWARE_VENDOR), (EFI_CHAR16 *)FIRMWARE_VENDOR);
737
738// TODO: Fill in other efi properties if necessary
739
740// Set up the /efi/runtime-services table node similar to the way a child node of configuration-table
741// is set up. That is, name and table properties
742Node *runtimeServicesNode = DT__AddChild(efiNode, "runtime-services");
743
744if (archCpuType == CPU_TYPE_I386) {
745// The value of the table property is the 32-bit physical address for the RuntimeServices table.
746// Since the EFI system table already has a pointer to it, we simply use the address of that pointer
747// for the pointer to the property data. Warning.. DT finalization calls free on that but we're not
748// the only thing to use a non-malloc'd pointer for something in the DT
749DT__AddProperty(runtimeServicesNode, "table", sizeof(EFI_UINT64), &gST32->RuntimeServices);
750} else {
751DT__AddProperty(runtimeServicesNode, "table", sizeof(EFI_UINT64), &gST64->RuntimeServices);
752}
753
754// Set up the /efi/configuration-table node which will eventually have several child nodes for
755// all of the configuration tables needed by various kernel extensions.
756gEfiConfigurationTableNode = DT__AddChild(efiNode, "configuration-table");
757
758// Set up the /efi/kernel-compatibility node only if 10.7 or better
759if (MacOSVerCurrent >= MacOSVer2Int("10.7"))
760{
761 Node *EfiKernelCompatNode = DT__AddChild(efiNode, "kernel-compatibility");
762 EFI_UINT8 compat = (archCpuType == CPU_TYPE_I386) ? 0b00000001 : 0b00000010;
763 getKernelCompat(&compat);
764 if (compat & 0b00000001) DT__AddProperty(EfiKernelCompatNode, "i386", sizeof(EFI_UINT32), (EFI_UINT32 *)&ONE_U32);
765 if (compat & 0b00000010) DT__AddProperty(EfiKernelCompatNode, "x86_64", sizeof(EFI_UINT32), (EFI_UINT32 *)&ONE_U32);
766 if (compat & 0b00000100) DT__AddProperty(EfiKernelCompatNode, "PPC", sizeof(EFI_UINT32), (EFI_UINT32 *)&ONE_U32);
767 if (compat & 0b00001000) DT__AddProperty(EfiKernelCompatNode, "PPC64", sizeof(EFI_UINT32), (EFI_UINT32 *)&ONE_U32);
768 }
769
770// Now fill in the /efi/platform Node
771Node *efiPlatformNode = DT__AddChild(efiNode, "platform");
772
773// NOTE WELL: If you do add FSB Frequency detection, make sure to store
774// the value in the fsbFrequency global and not an malloc'd pointer
775// because the DT_AddProperty function does not copy its args.
776
777if (Platform.CPU.FSBFrequency != 0) {
778DT__AddProperty(efiPlatformNode, FSB_Frequency_prop, sizeof(EFI_UINT64), (EFI_UINT64 *)&Platform.CPU.FSBFrequency);
779}
780
781// Export TSC and CPU frequencies for use by the kernel or KEXTs
782if (Platform.CPU.TSCFrequency != 0) {
783DT__AddProperty(efiPlatformNode, TSC_Frequency_prop, sizeof(EFI_UINT64), (EFI_UINT64 *)&Platform.CPU.TSCFrequency);
784}
785
786if (Platform.CPU.CPUFrequency != 0) {
787DT__AddProperty(efiPlatformNode, CPU_Frequency_prop, sizeof(EFI_UINT64), (EFI_UINT64 *)&Platform.CPU.CPUFrequency);
788}
789
790DT__AddProperty(efiPlatformNode, DEV_PATHS_SUP_PROP, sizeof(EFI_UINT32), (EFI_UINT32 *)&ONE_U32);
791
792// Bungo
793/* Export system-id. Can be disabled with SystemId=No in com.apple.Boot.plist
794if ((ret=getSystemID())) {
795DT__AddProperty(efiPlatformNode, SYSTEM_ID_PROP, UUID_LEN, (EFI_UINT32*) ret);
796}
797*/
798DT__AddProperty(efiPlatformNode, SYSTEM_ID_PROP, UUID_LEN, Platform.UUID);
799
800// Export SystemSerialNumber if present
801if ((ret16=getSmbiosChar16("SMserial", &len))) {
802DT__AddProperty(efiPlatformNode, SYSTEM_SERIAL_PROP, len, ret16);
803}
804
805// Export Model if present
806if ((ret16=getSmbiosChar16("SMproductname", &len))) {
807DT__AddProperty(efiPlatformNode, MODEL_PROP, len, ret16);
808}
809
810// Fill /efi/device-properties.
811setupDeviceProperties(efiNode);
812
813 // Add configuration table entries to both the services table and the device tree
814setupEfiConfigurationTable();
815}
816
817/*
818 * Must be called AFTER getSmbios
819 */
820void setupBoardId()
821{
822Node *node;
823node = DT__FindNode("/", false);
824if (node == 0)
825{
826stop("Couldn't get root '/' node");
827}
828const char *boardid = getStringForKey("SMboardproduct", &bootInfo->smbiosConfig);
829if (boardid)
830{
831DT__AddProperty(node, BOARDID_PROP, strlen(boardid)+1, (EFI_CHAR16 *)boardid);
832}
833}
834
835/*
836 * Fill up the root node
837 *
838setupRootNode()
839{
840
841}
842*/
843/*
844 * Fill up the chosen node
845 */
846void setupChosenNode()
847{
848Node *chosenNode = DT__FindNode("/chosen", false);
849if (chosenNode == NULL)
850{
851stop("setupChosenNode: Couldn't get '/chosen' node");
852}
853
854int length = strlen(gBootUUIDString);
855if (length)
856{
857DT__AddProperty(chosenNode, "boot-uuid", length + 1, gBootUUIDString);
858}
859
860length = strlen(bootArgs->CommandLine);
861DT__AddProperty(chosenNode, "boot-args", length + 1, bootArgs->CommandLine);
862
863length = strlen(bootInfo->bootFile);
864if (length)
865{
866 DT__AddProperty(chosenNode, "boot-file", length + 1, bootInfo->bootFile);
867 }
868// TODO:
869//DT__AddProperty(chosenNode, "boot-device-path", bootDPsize, gBootDP);
870//DT__AddProperty(chosenNode, "boot-file-path", bootFPsize, gBootFP);
871//DT__AddProperty(chosenNode, "boot-kernelchache-adler32", sizeof(adler32), adler32);
872
873DT__AddProperty(chosenNode, MACHINE_SIG_PROP, sizeof(Platform.HWSignature), (EFI_UINT32 *)&Platform.HWSignature);
874
875 // add if Yosemite or better only
876 if (MacOSVerCurrent >= MacOSVer2Int("10.10"))
877 {
878 //
879 // Pike R. Alpha - 12 October 2014
880 //
881 UInt8 index = 0;
882 EFI_UINT16 PMTimerValue = 0;
883 EFI_UINT32 randomValue, tempValue, cpuTick;
884 EFI_UINT32 ecx, esi, edi;
885 EFI_UINT32 rcx, rdx, rsi, rdi;
886
887 randomValue = tempValue = ecx = esi = edi = 0;// xor%ecx,%ecx
888 cpuTick = rcx = rdx = rsi = rdi = 0;
889
890 // LEAF_1 - Feature Information (Function 01h).
891 if (Platform.CPU.CPUID[CPUID_1][2] & 0x40000000)// Checking ecx:bit-30
892 {
893 //
894 // i5/i7 Ivy Bridge and Haswell processors with RDRAND support.
895 //
896 // EFI_UINT32 seedBuffer[16] = {0};
897 //
898 // Main loop to get 16 qwords (four bytes each).
899 //
900 EFI_UINT32 *seedPtr = (EFI_UINT32 *)RANDOM_SEED_PROP_VALUE;
901
902 for (index = 0; index < 16; index++)// 0x17e12:
903 {
904 randomValue = computeRand();// callq0x18e20
905 cpuTick = getCPUTick();// callq0x121a7
906 randomValue = (randomValue ^ cpuTick);// xor%rdi,%rax
907 seedPtr[index] = randomValue;// mov%rax,(%r15,%rsi,8)
908 }// jb0x17e12
909 }
910 else
911 {
912 //
913 // All other processors without RDRAND support.
914 //
915 // EFI_UINT8 seedBuffer[64] = {0};
916 //
917 // Main loop to get the 64 bytes.
918 //
919 EFI_UINT8 *seedPtr = (EFI_UINT8 *)RANDOM_SEED_PROP_VALUE;
920
921 do// 0x17e55:
922 {
923 PMTimerValue = inw(0x408);// in(%dx),%ax
924 esi = PMTimerValue;// movzwl%ax,%esi
925
926 if (esi < ecx)// cmp%ecx,%esi
927 {
928 continue;// jb0x17e55(retry)
929 }
930
931 cpuTick = getCPUTick();// callq0x121a7
932 rcx = (cpuTick >> 8);// mov%rax,%rcx
933 // shr$0x8,%rcx
934 rdx = (cpuTick >> 10);// mov%rax,%rdx
935 // shr$0x10,%rdx
936 rdi = rsi;// mov%rsi,%rdi
937 rdi = (rdi ^ cpuTick);// xor%rax,%rdi
938 rdi = (rdi ^ rcx);// xor%rcx,%rdi
939 rdi = (rdi ^ rdx);// xor%rdx,%rdi
940
941 //RANDOM_SEED_PROP_VALUE[index] = (EFI_UINT8)(rdi & 0xff);// mov%dil,(%r15,%r12,1)
942 seedPtr[index] = (EFI_UINT8)(rdi & 0xff);
943
944 edi = (edi & 0x2f);// and$0x2f,%edi
945 edi = (edi + esi);// add%esi,%edi
946 index++;// incr12
947 ecx = (edi & 0xffff);// movzwl%di,%ecx
948
949 } while (index < 64);// cmp%r14d,%r12d
950 // jne0x17e55(next)
951 }
952 DT__AddProperty(chosenNode, RANDOM_SEED_PROP, sizeof(RANDOM_SEED_PROP_VALUE), (EFI_UINT8 *)RANDOM_SEED_PROP_VALUE);
953 }
954
955 // setup '/chosen/memory-map' node
956 Node *memoryMapNode = DT__FindNode("/chosen/memory-map", false);
957if (memoryMapNode == NULL)
958{
959verbose("setupChosenNode:Couldn't get '/chosen/memory-map' node\n");
960} else { /*
961 static EFI_UINT64 BootClutPropValue = 0;
962 static EFI_UINT64 FailedBootPictPropValue = 0;
963 BootClutPropValue = ((EFI_UINT64)sizeof(appleClut8) << 32) | (EFI_UINT64)(EFI_UINT8 *)&appleClut8;
964 FailedBootPictPropValue = ((EFI_UINT64)(sizeof(gFailedBootPict) + 32) << 32) | (EFI_UINT64)(EFI_UINT8 *)&gFailedBootPict;
965 if (MacOSVerCurrent < MacOSVer2Int("10.7.3")) {
966 DT__AddProperty(node, "BootCLUT", sizeof(EFI_UINT64), (EFI_UINT64 *)&BootClutPropValue);
967 DT__AddProperty(node, "Pict-FailedBoot", sizeof(EFI_UINT64), (EFI_UINT64 *)&FailedBootPictPropValue);
968 } else {
969 DT__AddProperty(node, "FailedCLUT", sizeof(EFI_UINT64), (EFI_UINT64 *)&BootClutPropValue);
970 DT__AddProperty(node, "FailedImage", sizeof(EFI_UINT64), (EFI_UINT64 *)&FailedBootPictPropValue);
971 } */
972 }
973}
974
975/*
976 * Load the smbios.plist override config file if any
977 */
978static void setupSmbiosConfigFile()
979{
980//chardirSpecSMBIOS[256];
981const char*override_pathname = NULL;
982intlen = 0, err = 0;
983extern void scan_mem();
984
985// Take in account user overriding
986if (getValueForKey(kSMBIOSKey, &override_pathname, &len, &bootInfo->chameleonConfig) && len > 0)
987{
988// Specify a path to a file, e.g. SMBIOS=/Settings/macProXY.plist
989//sprintf(dirSpecSMBIOS, override_pathname);
990err = loadConfigFile(override_pathname, &bootInfo->smbiosConfig);
991}
992else
993{
994// Check selected volume's Extra.
995//sprintf(dirSpecSMBIOS, "/Extra/%s", filename);
996//if ( (err = loadConfigFile(dirSpecSMBIOS, &bootInfo->smbiosConfig)) )
997{
998// Check booter volume/rdbt Extra.
999//sprintf(dirSpecSMBIOS, "bt(0,0)/Extra/%s", filename);
1000err = loadConfigFile("/Extra/smbios.plist", &bootInfo->smbiosConfig);
1001}
1002}
1003
1004if (err)
1005{
1006 verbose("setupSmbiosConfigFile: no SMBIOS replacement found.\n");
1007}
1008
1009// get a chance to scan mem dynamically if user asks for it while having the config options
1010// loaded as well, as opposed to when it was in scan_platform(); also load the orig. smbios
1011// so that we can access dmi info, without patching the smbios yet.
1012scan_mem();
1013}
1014
1015void saveOriginalSMBIOS(void)
1016{
1017Node *node;
1018SMBEntryPoint *origeps;
1019void *tableAddress;
1020
1021node = DT__FindNode("/efi/platform", false);
1022if (!node)
1023{
1024verbose("saveOriginalSMBIOS: '/efi/platform' node not found\n");
1025return;
1026}
1027
1028origeps = getSmbios(SMBIOS_ORIGINAL);
1029if (!origeps)
1030{
1031 verbose("saveOriginalSMBIOS: original SMBIOS not found\n");
1032return;
1033}
1034
1035tableAddress = (void *)AllocateKernelMemory(origeps->dmi.tableLength);
1036if (!tableAddress)
1037{
1038 verbose("saveOriginalSMBIOS: can not allocate memory for original SMBIOS\n");
1039return;
1040}
1041
1042memcpy(tableAddress, (void *)origeps->dmi.tableAddress, origeps->dmi.tableLength);
1043DT__AddProperty(node, "SMBIOS", origeps->dmi.tableLength, tableAddress);
1044}
1045
1046char saveOriginalACPI()
1047{
1048 verbose("\nsaveOriginalACPI: Saving OEM tables into IODT:/chosen/acpi...\n");
1049
1050 Node *node = DT__FindNode("/chosen/acpi", true);
1051if (!node)
1052{
1053 verbose("saveOriginalACPI: node '/chosen/acpi' not found, can't save any OEM tables.\n\n");
1054 return 0;
1055 }
1056
1057 struct acpi_2_rsdp *RSDP = getRSDPaddress();
1058
1059 if (!RSDP) {
1060 verbose("saveOriginalACPI: OEM RSDP not found or incorrect, can't save any OEM tables.\n\n");
1061 return 0;
1062 }
1063
1064 uint8_t r,
1065 total_number = 1,
1066 ssdt_number = 0,
1067 nameLen = strlen("XXXX@XXXXXXXX");
1068 uint32_t length = RSDP->Revision ? RSDP->Length : 20;
1069 char *nameBuf = malloc(nameLen);
1070
1071 sprintf(nameBuf, "RSDP@%08X", (uint32_t)RSDP);
1072 verbose("saveOriginalACPI: OEM table %s found, length=%d: saving.\n", nameBuf, length);
1073 DT__AddProperty(node, nameBuf, length, RSDP);
1074 uint32_t total_length = length;
1075
1076 struct acpi_2_header *RSDT = (struct acpi_2_header *)(RSDP->RsdtAddress),
1077 *XSDT = (struct acpi_2_header *)(uint32_t)(RSDP->XsdtAddress);
1078
1079 void *origTable = NULL,
1080 *origTable2 = NULL,
1081 *origTable3 = NULL,
1082 *origTable4 = NULL;
1083
1084 if ((RSDP->RsdtAddress > 0) && (RSDP->RsdtAddress < 0xFFFFFFFF) && tableSign(RSDT->Signature, "RSDT")) {
1085 origTable = (void *)(RSDT + 1);
1086 nameBuf = malloc(nameLen + 1);
1087 sprintf(nameBuf, "RSDT@%08X", (uint32_t)RSDT);
1088 verbose("saveOriginalACPI: OEM table %s found, lenght=%d: saving.\n", nameBuf, RSDT->Length);
1089 DT__AddProperty(node, nameBuf, RSDT->Length, RSDT);
1090 total_length += RSDT->Length;
1091 total_number++;
1092 for ( ; origTable < ((void *)RSDT + RSDT->Length); origTable += 4) {
1093 origTable2 = (void *)(*(uint32_t *)origTable);
1094 length = ((struct acpi_2_header *)origTable2)->Length;
1095 total_length += length;
1096 total_number++;
1097 if (tableSign(((struct acpi_2_header *)origTable2)->Signature, "SSDT")) {
1098 ssdt_number++;
1099 if (strcmp(((struct acpi_2_header *)origTable2)->OEMTableId, "CpuPm") == 0) {
1100 nameLen = strlen("SSDT@XXXXXXXX");
1101 nameBuf = malloc(nameLen + 1);
1102 sprintf(nameBuf, "SSDT@%08X", (uint32_t)origTable2);
1103 verbose("saveOriginalACPI: OEM table %s found, lenght=%d: saving.\n", nameBuf, length);
1104 DT__AddProperty(node, nameBuf, length, origTable2);
1105 origTable2 += sizeof(struct acpi_2_header) + 15;
1106 r = *((uint8_t *)origTable2 - 2) / 3; // e.g: Name (SSDT, Package (0x0C) -> 0x0C / 3 = 4 is number of sub SSDTs
1107 for (; r > 0; r--, origTable2 += sizeof(struct ssdt_pmref)) {
1108 origTable3 = (void *)(((struct ssdt_pmref *)origTable2)->addr);
1109 if (!((uint32_t)origTable3 > 0) && !((uint32_t)origTable3 < 0xFFFFFFFF)) continue; // incorrect, dropping
1110 length = ((struct acpi_2_header *)origTable3)->Length;
1111 nameLen = strlen("SSDT_@XXXXXXXX") + strlen((char *)((struct acpi_2_header *)origTable3)->OEMTableId);
1112 nameBuf = malloc(nameLen + 1);
1113 sprintf(nameBuf, "SSDT_%s@%08X", (char *)((struct acpi_2_header *)origTable3)->OEMTableId, (uint32_t)origTable3);
1114 verbose("saveOriginalACPI: OEM table %s found, lenght=%d: saving.\n", nameBuf, length);
1115 DT__AddProperty(node, nameBuf, length, origTable3);
1116 total_length += length;
1117 total_number++;
1118 }
1119 } else {
1120 nameLen = strlen("SSDT-@XXXXXXXX") + ((ssdt_number < 10)? 1:2);
1121 nameBuf = malloc(nameLen + 1);
1122 sprintf(nameBuf, "SSDT-%d@%08X", ssdt_number, (uint32_t)origTable2);
1123 verbose("saveOriginalACPI: OEM table %s found, lenght=%d: saving.\n", nameBuf, length);
1124 DT__AddProperty(node, nameBuf, length, origTable2);
1125 }
1126 } else {
1127 nameLen = strlen("XXXX@XXXXXXXX");
1128 nameBuf = malloc(nameLen + 1);
1129 sprintf(nameBuf, "%c%c%c%c@%08X", ((char *)origTable2)[0], ((char *)origTable2)[1], ((char *)origTable2)[2], ((char *)origTable2)[3], (uint32_t)origTable2);
1130 verbose("saveOriginalACPI: OEM table %s found, lenght=%d: saving.\n", nameBuf, length);
1131 DT__AddProperty(node, nameBuf, length, origTable2);
1132 if (tableSign(((struct acpi_2_header *)origTable2)->Signature, "FACP")) {
1133 origTable3 = (void *)(((struct acpi_2_fadt *)origTable2)->FACS);
1134 length = ((struct acpi_2_header *)origTable3)->Length;
1135 nameLen = strlen("FACS@XXXXXXXX");
1136 nameBuf = malloc(nameLen + 1);
1137 sprintf(nameBuf, "FACS@%08X", (uint32_t)origTable3);
1138 verbose("saveOriginalACPI: OEM table %s found, lenght=%d: saving.\n", nameBuf, length);
1139 DT__AddProperty(node, nameBuf, length, origTable3);
1140 total_length += length;
1141 total_number++;
1142 origTable3 = (void *)(((struct acpi_2_fadt *)origTable2)->DSDT);
1143 length = ((struct acpi_2_header *)origTable3)->Length;
1144 nameLen = strlen("DSDT@XXXXXXXX");
1145 nameBuf = malloc(nameLen + 1);
1146 sprintf(nameBuf, "DSDT@%08X", (uint32_t)origTable3);
1147 verbose("saveOriginalACPI: OEM table %s found, lenght=%d: saving.\n", nameBuf, length);
1148 DT__AddProperty(node, nameBuf, length, origTable3);
1149 total_length += length;
1150 total_number++;
1151 }
1152 }
1153 }
1154 } else {
1155 verbose("saveOriginalACPI: OEM table RSDT@%08x not found or incorrect.\n", RSDP->RsdtAddress);
1156 }
1157 if (gVerboseMode) pause("");
1158
1159 if (RSDP->Revision > 0) {
1160 verbose("\n");
1161 if ((RSDP->XsdtAddress > 0) && (RSDP->XsdtAddress < 0xFFFFFFFF) && tableSign(XSDT->Signature, "XSDT")) {
1162 verbose("saveOriginalACPI: OEM table XSDT@%016X found, lenght=%d: saving.\n", (uint32_t)XSDT, XSDT->Length);
1163 nameLen = strlen("XSDT@XXXXXXXX");
1164 nameBuf = malloc(nameLen + 1);
1165 sprintf(nameBuf, "XSDT@%08X", (uint32_t)XSDT);
1166 DT__AddProperty(node, nameBuf, XSDT->Length, XSDT);
1167 total_number++;
1168 total_length += XSDT->Length;
1169 for (origTable = (void *)(RSDT + 1), origTable4 = (void *)(XSDT + 1); origTable4 < ((void *)XSDT + XSDT->Length); origTable += 4, origTable4 += 8) {
1170 origTable2 = (void *)(uint32_t)(*(uint64_t *)origTable4);
1171 length = ((struct acpi_2_header *)origTable2)->Length;
1172 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);
1173 if (*(uint32_t *)origTable != (uint32_t)origTable2) { // already saved?
1174 verbose("saving.\n");
1175 nameLen = strlen("X_XXXX@XXXXXXXX");
1176 nameBuf = malloc(nameLen + 1);
1177 sprintf(nameBuf, "X_%c%c%c%c@%08X", ((char *)origTable2)[0], ((char *)origTable2)[1], ((char *)origTable2)[2], ((char *)origTable2)[3], (uint32_t)origTable2);
1178 DT__AddProperty(node, nameBuf, length, origTable2);
1179 total_length += length;
1180 total_number++;
1181
1182 if (tableSign(((struct acpi_2_header *)origTable2)->Signature, "SSDT") && (strcmp(((struct acpi_2_header *)origTable2)->OEMTableId, "CpuPm") == 0)) {
1183 // Get rest of ssdts from ssdt_pmref
1184 r = *((uint8_t *)origTable2 - 2) / 3; // e.g: Name (SSDT, Package (0x0C) -> 0x0C / 3 = 4 is number of sub SSDTs
1185 for (; r > 0; r--, origTable2 += sizeof(struct ssdt_pmref)) {
1186 origTable3 = (void *)(((struct ssdt_pmref *)origTable2)->addr);
1187 if (!((uint32_t)origTable3 > 0) && !((uint32_t)origTable3 < 0xFFFFFFFF)) continue; // incorrect, dropping
1188 length = ((struct acpi_2_header *)origTable3)->Length;
1189 nameLen = strlen("SSDT_@XXXXXXXX") + strlen((char *)((struct acpi_2_header *)origTable3)->OEMTableId);
1190 nameBuf = malloc(nameLen + 1);
1191 sprintf(nameBuf, "SSDT_%s@%08X", (char *)((struct acpi_2_header *)origTable3)->OEMTableId, (uint32_t)origTable3);
1192 verbose("saveOriginalACPI: OEM table %s found, lenght=%d: saving.\n", nameBuf, length);
1193 DT__AddProperty(node, nameBuf, length, origTable3);
1194 total_length += length;
1195 total_number++;
1196 }
1197 continue;
1198 }
1199
1200 if (tableSign(((struct acpi_2_header *)origTable2)->Signature, "FACP")) {
1201 origTable3 = (void *)(((struct acpi_2_fadt *)origTable2)->X_FACS); // take x_facs assuming facs (from x_facp) should be equal to it
1202 length = ((struct acpi_2_rsdt *)origTable3)->Length;
1203 verbose("saveOriginalACPI: OEM table X_FACS@%016X found, lenght=%d: ", (uint32_t)origTable3, length);
1204 if (origTable3 != (void *)(((struct acpi_2_fadt *)origTable2)->FACS)) {
1205 verbose("saving.\n");
1206 nameLen = strlen("X_FACS@XXXXXXXX");
1207 nameBuf = malloc(nameLen + 1);
1208 sprintf(nameBuf, "X_FACS@%08X", (uint32_t)origTable3);
1209 DT__AddProperty(node, nameBuf, length, origTable3);
1210 total_length += length;
1211 total_number++;
1212 } else {
1213 verbose("already saved.\n");
1214 }
1215 // assuming only one dsdt in system, so x_facp should contain pointer to it same as facp
1216 origTable3 = (void *)(((struct acpi_2_fadt *)origTable2)->X_DSDT);
1217 length = ((struct acpi_2_rsdt *)origTable3)->Length;
1218 verbose("saveOriginalACPI: OEM table X_DSDT@%016X found, lenght=%d: ", origTable3, length);
1219 if (origTable3 != (void *)(((struct acpi_2_fadt *)origTable2)->DSDT)) {
1220 verbose("saving.\n");
1221 nameLen = strlen("X_DSDT@XXXXXXXX");
1222 nameBuf = malloc(nameLen + 1);
1223 sprintf(nameBuf, "X_DSDT@%08X", origTable3);
1224 DT__AddProperty(node, nameBuf, length, origTable3);
1225 total_length += length;
1226 total_number++;
1227 } else {
1228 verbose("already saved.\n");
1229 }
1230 continue;
1231 }
1232 } else {
1233 verbose("already saved.\n");
1234 }
1235 }
1236 } else {
1237 verbose("saveOriginalACPI: OEM table XSDT@%08X%08X not found or incorrect.\n", (uint32_t)(RSDP->XsdtAddress >> 32), (uint32_t)(RSDP->XsdtAddress & 0xFFFFFFFF));
1238 }
1239 }
1240
1241 if (!RSDT && !XSDT) {
1242 verbose("saveOriginalACPI: OEM RSDT & XSDT not found or incorrect, can't save any tables.\n\n");
1243 return 0;
1244 }
1245
1246 verbose("saveOriginalACPI: %d OEM table%s found and saved, total lenght=%d.\n\n", total_number, (total_number != 1) ? "s" : "", total_length);
1247 if (gVerboseMode) pause("");
1248
1249 return total_number;
1250}
1251
1252/*
1253 * Entrypoint from boot.c
1254 */
1255void setupFakeEfi(void)
1256{
1257// Generate efi device strings
1258setup_pci_devs(root_pci_dev);
1259
1260readSMBIOSInfo(getSmbios(SMBIOS_ORIGINAL));
1261
1262// load smbios.plist file if any
1263setupSmbiosConfigFile();
1264
1265 // Setup ACPI with DSDT overrides (mackerintel's patch)
1266setupAcpi();
1267
1268 setupSMBIOS();
1269
1270 // Setup board-id: need to be called after getSmbios!
1271 setupBoardId();
1272
1273 // Setup system-type: We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()
1274// because we need to take care of FACP original content, if it is correct.
1275setupSystemType();
1276
1277 // Setup the '/' node
1278//setupRootNode();
1279
1280// Setup the '/chosen' node
1281setupChosenNode();
1282
1283// Initialize the base table
1284if (archCpuType == CPU_TYPE_I386)
1285{
1286setupEfiTables32();
1287}
1288else
1289{
1290setupEfiTables64();
1291}
1292
1293 // Setup efi node
1294setupEfiNode();
1295
1296 saveOriginalSMBIOS();
1297
1298 saveOriginalACPI();
1299}
1300

Archive Download this file

Revision: 2537