Chameleon

Chameleon Svn Source Tree

Root/branches/slice/old749m/i386/libsaio/fake_efi.c

1
2/*
3 * Copyright 2007 David F. Elliott. All rights reserved.
4 */
5
6#include "libsaio.h"
7#include "boot.h"
8#include "bootstruct.h"
9#include "efi.h"
10#include "acpi.h"
11#include "fake_efi.h"
12#include "efi_tables.h"
13#include "platform.h"
14#include "acpi_patcher.h"
15#include "smbios_patcher.h"
16#include "device_inject.h"
17#include "convert.h"
18#include "pci.h"
19#include "sl.h"
20//#include "mem.h"
21#include "modules.h"
22
23#ifdef static
24#undef static
25#endif
26
27//BLESS_EFI_LOAD_OPTION* BootOrder;
28extern struct SMBEntryPoint * getSmbios(int which); // now cached
29//extern void setup_pci_devs(pci_dt_t *pci_dt);
30
31#define kBL_GLOBAL_NVRAM_GUID "8BE4DF61-93CA-11D2-AA0D-00E098032B8C"
32
33// Check if a system supports CSM legacy mode
34#define kBL_APPLE_VENDOR_NVRAM_GUID "4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14"
35
36/*
37 * Modern Darwin kernels require some amount of EFI because Apple machines all
38 * have EFI. Modifying the kernel source to not require EFI is of course
39 * possible but would have to be maintained as a separate patch because it is
40 * unlikely that Apple wishes to add legacy support to their kernel.
41 *
42 * As you can see from the Apple-supplied code in bootstruct.c, it seems that
43 * the intention was clearly to modify this booter to provide EFI-like structures
44 * to the kernel rather than modifying the kernel to handle non-EFI stuff. This
45 * makes a lot of sense from an engineering point of view as it means the kernel
46 * for the as yet unreleased EFI-only Macs could still be booted by the non-EFI
47 * DTK systems so long as the kernel checked to ensure the boot tables were
48 * filled in appropriately. Modern xnu requires a system table and a runtime
49 * services table and performs no checks whatsoever to ensure the pointers to
50 * these tables are non-NULL.Therefore, any modern xnu kernel will page fault
51 * early on in the boot process if the system table pointer is zero.
52 *
53 * Even before that happens, the tsc_init function in modern xnu requires the FSB
54 * Frequency to be a property in the /efi/platform node of the device tree or else
55 * it panics the bootstrap process very early on.
56 *
57 * As of this writing, the current implementation found here is good enough
58 * to make the currently available xnu kernel boot without modification on a
59 * system with an appropriate processor. With a minor source modification to
60 * the tsc_init function to remove the explicit check for Core or Core 2
61 * processors the kernel can be made to boot on other processors so long as
62 * the code can be executed by the processor and the machine contains the
63 * necessary hardware.
64 */
65
66/*==========================================================================
67 * Utility function to make a device tree string from an EFI_GUID
68 */
69
70static inline char * mallocStringForGuid(EFI_GUID const *pGuid)
71{
72char *string = malloc(37);
73efi_guid_unparse_upper(pGuid, string);
74return string;
75}
76
77/*==========================================================================
78 * Function to map 32 bit physical address to 64 bit virtual address
79 */
80
81static uint64_t ptov64(uint32_t addr)
82{
83return ((uint64_t)addr | 0xFFFFFF8000000000ULL);
84}
85
86/*==========================================================================
87 * Fake EFI implementation
88 */
89
90/* Identify ourselves as the EFI firmware vendor */
91static EFI_CHAR16 const FIRMWARE_VENDOR[] = {'C','h','a','m','e','l','e','o','n','_','2','.','5','M', 0};
92static EFI_UINT32 const FIRMWARE_REVISION = 0x0001000a;
93static EFI_UINT32 const FIRMWARE_FEATURE_MASK = 0x000003FF;
94static EFI_UINT32 const STATIC_ZERO = 0;
95
96/* Default platform system_id (fix by IntVar) */
97//static EFI_CHAR8 const SYSTEM_ID[] = "0123456789ABCDEF"; //random value gen by uuidgen
98
99/* Just a ret instruction */
100static uint8_t const VOIDRET_INSTRUCTIONS[] = {0xc3};
101
102/* movl $0x80000003,%eax; ret */
103static uint8_t const UNSUPPORTEDRET_INSTRUCTIONS[] = {0xb8, 0x03, 0x00, 0x00, 0x80, 0xc3};
104//#define SYSTEM_ID_DEFAULT {0x41, 0x73, 0x65, 0x72, 0x65, 0x42, 0x4c, 0x4e, 0x66, 0x75, 0x63, 0x6b, 0x45, 0x46, 0x49, 0x58}
105EFI_GUID const SYSTEM_ID_DEFAULT = {0x72657341, 0x4265, 0x4e4C, 0x66, 0x75, {0x63, 0x6b, 0x45, 0x46, 0x49, 0x58}};
106EFI_SYSTEM_TABLE_32 *gST32 = NULL;
107EFI_SYSTEM_TABLE_64 *gST64 = NULL;
108Node *gEfiConfigurationTableNode = NULL;
109
110extern EFI_STATUS addConfigurationTable(EFI_GUID const *pGuid, void *table, char const *alias)
111{
112EFI_UINTN i = 0;
113
114//Azi: as is, cpu's with em64t will use EFI64 on pre 10.6 systems,
115// wich seems to cause no problem. In case it does, force i386 arch.
116if (archCpuType == CPU_TYPE_I386)
117{
118i = gST32->NumberOfTableEntries;
119}
120else
121{
122i = gST64->NumberOfTableEntries;
123}
124
125// We only do adds, not modifications and deletes like InstallConfigurationTable
126if (i >= MAX_CONFIGURATION_TABLE_ENTRIES)
127stop("Ran out of space for configuration tables. Increase the reserved size in the code.\n");
128
129if (pGuid == NULL)
130return EFI_INVALID_PARAMETER;
131
132if (table != NULL)
133{
134// FIXME
135//((EFI_CONFIGURATION_TABLE_64 *)gST->ConfigurationTable)[i].VendorGuid = *pGuid;
136//((EFI_CONFIGURATION_TABLE_64 *)gST->ConfigurationTable)[i].VendorTable = (EFI_PTR64)table;
137
138//++gST->NumberOfTableEntries;
139
140Node *tableNode = DT__AddChild(gEfiConfigurationTableNode, mallocStringForGuid(pGuid));
141
142// Use the pointer to the GUID we just stuffed into the system table
143DT__AddProperty(tableNode, "guid", sizeof(EFI_GUID), (void*)pGuid);
144
145// The "table" property is the 32-bit (in our implementation) physical address of the table
146DT__AddProperty(tableNode, "table", sizeof(void*) * 2, table);
147
148// Assume the alias pointer is a global or static piece of data
149if (alias != NULL)
150DT__AddProperty(tableNode, "alias", strlen(alias)+1, (char*)alias);
151
152return EFI_SUCCESS;
153}
154return EFI_UNSUPPORTED;
155}
156
157//Azi: crc32 done in place, on the cases were it wasn't.
158/*static inline void fixupEfiSystemTableCRC32(EFI_SYSTEM_TABLE_64 *efiSystemTable)
159{
160efiSystemTable->Hdr.CRC32 = 0;
161efiSystemTable->Hdr.CRC32 = crc32(0L, efiSystemTable, efiSystemTable->Hdr.HeaderSize);
162}*/
163
164/*
165 * What we do here is simply allocate a fake EFI system table and a fake EFI
166 * runtime services table.
167 *
168 * Because we build against modern headers with kBootArgsRevision 4 we
169 * also take care to set efiMode = 32.
170 */
171
172void setupEfiTables32(void)
173{
174// We use the fake_efi_pages struct so that we only need to do one kernel
175// memory allocation for all needed EFI data. Otherwise, small allocations
176// like the FIRMWARE_VENDOR string would take up an entire page.
177// NOTE WELL: Do NOT assume this struct has any particular layout within itself.
178// It is absolutely not intended to be publicly exposed anywhere
179// We say pages (plural) although right now we are well within the 1 page size
180// and probably will stay that way.
181struct fake_efi_pages
182{
183EFI_SYSTEM_TABLE_32 efiSystemTable;
184EFI_RUNTIME_SERVICES_32 efiRuntimeServices;
185EFI_CONFIGURATION_TABLE_32 efiConfigurationTable[MAX_CONFIGURATION_TABLE_ENTRIES];
186EFI_CHAR16 firmwareVendor[sizeof(FIRMWARE_VENDOR)/sizeof(EFI_CHAR16)];
187uint8_t voidret_instructions[sizeof(VOIDRET_INSTRUCTIONS)/sizeof(uint8_t)];
188uint8_t unsupportedret_instructions[sizeof(UNSUPPORTEDRET_INSTRUCTIONS)/sizeof(uint8_t)];
189};
190
191struct fake_efi_pages *fakeEfiPages = (struct fake_efi_pages*)AllocateKernelMemory(sizeof(struct fake_efi_pages));
192
193// Zero out all the tables in case fields are added later
194bzero(fakeEfiPages, sizeof(struct fake_efi_pages));
195
196// --------------------------------------------------------------------
197// Initialize some machine code that will return EFI_UNSUPPORTED for
198// functions returning int and simply return for void functions.
199memcpy(fakeEfiPages->voidret_instructions, VOIDRET_INSTRUCTIONS, sizeof(VOIDRET_INSTRUCTIONS));
200memcpy(fakeEfiPages->unsupportedret_instructions, UNSUPPORTEDRET_INSTRUCTIONS, sizeof(UNSUPPORTEDRET_INSTRUCTIONS));
201
202// --------------------------------------------------------------------
203// System table
204EFI_SYSTEM_TABLE_32 *efiSystemTable = gST32 = &fakeEfiPages->efiSystemTable;
205efiSystemTable->Hdr.Signature = EFI_SYSTEM_TABLE_SIGNATURE;
206efiSystemTable->Hdr.Revision = EFI_SYSTEM_TABLE_REVISION;
207efiSystemTable->Hdr.HeaderSize = sizeof(EFI_SYSTEM_TABLE_32);
208efiSystemTable->Hdr.CRC32 = 0; // Initialize to zero and then do CRC32
209efiSystemTable->Hdr.Reserved = 0;
210
211efiSystemTable->FirmwareVendor = (EFI_PTR32)&fakeEfiPages->firmwareVendor;
212memcpy(fakeEfiPages->firmwareVendor, FIRMWARE_VENDOR, sizeof(FIRMWARE_VENDOR));
213efiSystemTable->FirmwareRevision = FIRMWARE_REVISION;
214
215// XXX: We may need to have basic implementations of ConIn/ConOut/StdErr
216// The EFI spec states that all handles are invalid after boot services have been
217// exited so we can probably get by with leaving the handles as zero.
218efiSystemTable->ConsoleInHandle = 0;
219efiSystemTable->ConIn = 0;
220
221efiSystemTable->ConsoleOutHandle = 0;
222efiSystemTable->ConOut = 0;
223
224efiSystemTable->StandardErrorHandle = 0;
225efiSystemTable->StdErr = 0;
226
227efiSystemTable->RuntimeServices = (EFI_PTR32)&fakeEfiPages->efiRuntimeServices;
228
229// According to the EFI spec, BootServices aren't valid after the
230// boot process is exited so we can probably do without it.
231// Apple didn't provide a definition for it in pexpert/i386/efi.h
232// so I'm guessing they don't use it.
233efiSystemTable->BootServices = 0;
234
235efiSystemTable->NumberOfTableEntries = 0;
236efiSystemTable->ConfigurationTable = (EFI_PTR32)fakeEfiPages->efiConfigurationTable;
237
238// We're done. Now CRC32 the thing so the kernel will accept it.
239// Must be initialized to zero before CRC32, done above.
240gST32->Hdr.CRC32 = crc32(0L, gST32, gST32->Hdr.HeaderSize);
241
242// --------------------------------------------------------------------
243// Runtime services
244EFI_RUNTIME_SERVICES_32 *efiRuntimeServices = &fakeEfiPages->efiRuntimeServices;
245efiRuntimeServices->Hdr.Signature = EFI_RUNTIME_SERVICES_SIGNATURE;
246efiRuntimeServices->Hdr.Revision = EFI_RUNTIME_SERVICES_REVISION;
247efiRuntimeServices->Hdr.HeaderSize = sizeof(EFI_RUNTIME_SERVICES_32);
248efiRuntimeServices->Hdr.CRC32 = 0;
249efiRuntimeServices->Hdr.Reserved = 0;
250
251// There are a number of function pointers in the efiRuntimeServices table.
252// These are the Foundation (e.g. core) services and are expected to be present on
253// all EFI-compliant machines.Some kernel extensions (notably AppleEFIRuntime)
254// will call these without checking to see if they are null.
255//
256// We don't really feel like doing an EFI implementation in the bootloader
257// but it is nice if we can at least prevent a complete crash by
258// at least providing some sort of implementation until one can be provided
259// nicely in a kext.
260void (*voidret_fp)() = (void*)fakeEfiPages->voidret_instructions;
261void (*unsupportedret_fp)() = (void*)fakeEfiPages->unsupportedret_instructions;
262efiRuntimeServices->GetTime = (EFI_PTR32)unsupportedret_fp;
263efiRuntimeServices->SetTime = (EFI_PTR32)unsupportedret_fp;
264efiRuntimeServices->GetWakeupTime = (EFI_PTR32)unsupportedret_fp;
265efiRuntimeServices->SetWakeupTime = (EFI_PTR32)unsupportedret_fp;
266efiRuntimeServices->SetVirtualAddressMap = (EFI_PTR32)unsupportedret_fp;
267efiRuntimeServices->ConvertPointer = (EFI_PTR32)unsupportedret_fp;
268efiRuntimeServices->GetVariable = (EFI_PTR32)unsupportedret_fp;
269efiRuntimeServices->GetNextVariableName = (EFI_PTR32)unsupportedret_fp;
270efiRuntimeServices->SetVariable = (EFI_PTR32)unsupportedret_fp;
271efiRuntimeServices->GetNextHighMonotonicCount = (EFI_PTR32)unsupportedret_fp;
272efiRuntimeServices->ResetSystem = (EFI_PTR32)voidret_fp;
273
274// We're done.Now CRC32 the thing so the kernel will accept it
275efiRuntimeServices->Hdr.CRC32 = crc32(0L, efiRuntimeServices, efiRuntimeServices->Hdr.HeaderSize);
276
277// --------------------------------------------------------------------
278// Finish filling in the rest of the boot args that we need.
279bootArgs->efiSystemTable = (uint32_t)efiSystemTable;
280bootArgs->efiMode = kBootArgsEfiMode32;
281
282// The bootArgs structure as a whole is bzero'd so we don't need to fill in
283// things like efiRuntimeServices* and what not.
284//
285// In fact, the only code that seems to use that is the hibernate code so it
286// knows not to save the pages. It even checks to make sure its nonzero.
287}
288
289void setupEfiTables64(void)
290{
291struct fake_efi_pages
292{
293EFI_SYSTEM_TABLE_64 efiSystemTable;
294EFI_RUNTIME_SERVICES_64 efiRuntimeServices;
295EFI_CONFIGURATION_TABLE_64 efiConfigurationTable[MAX_CONFIGURATION_TABLE_ENTRIES];
296EFI_CHAR16 firmwareVendor[sizeof(FIRMWARE_VENDOR)/sizeof(EFI_CHAR16)];
297uint8_t voidret_instructions[sizeof(VOIDRET_INSTRUCTIONS)/sizeof(uint8_t)];
298uint8_t unsupportedret_instructions[sizeof(UNSUPPORTEDRET_INSTRUCTIONS)/sizeof(uint8_t)];
299};
300
301struct fake_efi_pages *fakeEfiPages = (struct fake_efi_pages*)AllocateKernelMemory(sizeof(struct fake_efi_pages));
302
303// Zero out all the tables in case fields are added later
304bzero(fakeEfiPages, sizeof(struct fake_efi_pages));
305
306// --------------------------------------------------------------------
307// Initialize some machine code that will return EFI_UNSUPPORTED for
308// functions returning int and simply return for void functions.
309memcpy(fakeEfiPages->voidret_instructions, VOIDRET_INSTRUCTIONS, sizeof(VOIDRET_INSTRUCTIONS));
310memcpy(fakeEfiPages->unsupportedret_instructions, UNSUPPORTEDRET_INSTRUCTIONS, sizeof(UNSUPPORTEDRET_INSTRUCTIONS));
311
312// --------------------------------------------------------------------
313// System table
314EFI_SYSTEM_TABLE_64 *efiSystemTable = gST64 = &fakeEfiPages->efiSystemTable;
315efiSystemTable->Hdr.Signature = EFI_SYSTEM_TABLE_SIGNATURE;
316efiSystemTable->Hdr.Revision = EFI_SYSTEM_TABLE_REVISION;
317efiSystemTable->Hdr.HeaderSize = sizeof(EFI_SYSTEM_TABLE_64);
318efiSystemTable->Hdr.CRC32 = 0; // Initialize to zero and then do CRC32
319efiSystemTable->Hdr.Reserved = 0;
320
321efiSystemTable->FirmwareVendor = ptov64((EFI_PTR32)&fakeEfiPages->firmwareVendor);
322memcpy(fakeEfiPages->firmwareVendor, FIRMWARE_VENDOR, sizeof(FIRMWARE_VENDOR));
323efiSystemTable->FirmwareRevision = FIRMWARE_REVISION;
324
325// XXX: We may need to have basic implementations of ConIn/ConOut/StdErr
326// The EFI spec states that all handles are invalid after boot services have been
327// exited so we can probably get by with leaving the handles as zero.
328efiSystemTable->ConsoleInHandle = 0;
329efiSystemTable->ConIn = 0;
330
331efiSystemTable->ConsoleOutHandle = 0;
332efiSystemTable->ConOut = 0;
333
334efiSystemTable->StandardErrorHandle = 0;
335efiSystemTable->StdErr = 0;
336
337efiSystemTable->RuntimeServices = ptov64((EFI_PTR32)&fakeEfiPages->efiRuntimeServices);
338// According to the EFI spec, BootServices aren't valid after the
339// boot process is exited so we can probably do without it.
340// Apple didn't provide a definition for it in pexpert/i386/efi.h
341// so I'm guessing they don't use it.
342efiSystemTable->BootServices = 0;
343
344efiSystemTable->NumberOfTableEntries = 0;
345efiSystemTable->ConfigurationTable = ptov64((EFI_PTR32)fakeEfiPages->efiConfigurationTable);
346
347// We're done.Now CRC32 the thing so the kernel will accept it
348gST64->Hdr.CRC32 = crc32(0L, gST64, gST64->Hdr.HeaderSize);
349
350// --------------------------------------------------------------------
351// Runtime services
352EFI_RUNTIME_SERVICES_64 *efiRuntimeServices = &fakeEfiPages->efiRuntimeServices;
353efiRuntimeServices->Hdr.Signature = EFI_RUNTIME_SERVICES_SIGNATURE;
354efiRuntimeServices->Hdr.Revision = EFI_RUNTIME_SERVICES_REVISION;
355efiRuntimeServices->Hdr.HeaderSize = sizeof(EFI_RUNTIME_SERVICES_64);
356efiRuntimeServices->Hdr.CRC32 = 0;
357efiRuntimeServices->Hdr.Reserved = 0;
358
359// There are a number of function pointers in the efiRuntimeServices table.
360// These are the Foundation (e.g. core) services and are expected to be present on
361// all EFI-compliant machines.Some kernel extensions (notably AppleEFIRuntime)
362// will call these without checking to see if they are null.
363//
364// We don't really feel like doing an EFI implementation in the bootloader
365// but it is nice if we can at least prevent a complete crash by
366// at least providing some sort of implementation until one can be provided
367// nicely in a kext.
368
369void (*voidret_fp)() = (void*)fakeEfiPages->voidret_instructions;
370void (*unsupportedret_fp)() = (void*)fakeEfiPages->unsupportedret_instructions;
371efiRuntimeServices->GetTime = ptov64((EFI_PTR32)unsupportedret_fp);
372efiRuntimeServices->SetTime = ptov64((EFI_PTR32)unsupportedret_fp);
373efiRuntimeServices->GetWakeupTime = ptov64((EFI_PTR32)unsupportedret_fp);
374efiRuntimeServices->SetWakeupTime = ptov64((EFI_PTR32)unsupportedret_fp);
375efiRuntimeServices->SetVirtualAddressMap = ptov64((EFI_PTR32)unsupportedret_fp);
376efiRuntimeServices->ConvertPointer = ptov64((EFI_PTR32)unsupportedret_fp);
377efiRuntimeServices->GetVariable = ptov64((EFI_PTR32)unsupportedret_fp);
378efiRuntimeServices->GetNextVariableName = ptov64((EFI_PTR32)unsupportedret_fp);
379efiRuntimeServices->SetVariable = ptov64((EFI_PTR32)unsupportedret_fp);
380efiRuntimeServices->GetNextHighMonotonicCount = ptov64((EFI_PTR32)unsupportedret_fp);
381efiRuntimeServices->ResetSystem = ptov64((EFI_PTR32)voidret_fp);
382
383// We're done.Now CRC32 the thing so the kernel will accept it
384efiRuntimeServices->Hdr.CRC32 = crc32(0L, efiRuntimeServices, efiRuntimeServices->Hdr.HeaderSize);
385
386// --------------------------------------------------------------------
387// Finish filling in the rest of the boot args that we need.
388bootArgs->efiSystemTable = (uint32_t)efiSystemTable;
389bootArgs->efiMode = kBootArgsEfiMode64;
390
391// The bootArgs structure as a whole is bzero'd so we don't need to fill in
392// things like efiRuntimeServices* and what not.
393//
394// In fact, the only code that seems to use that is the hibernate code so it
395// knows not to save the pages. It even checks to make sure its nonzero.
396}
397
398/*
399 * In addition to the EFI tables there is also the EFI device tree node.
400 * In particular, we need /efi/platform to have an FSBFrequency key. Without it,
401 * the tsc_init function will panic very early on in kernel startup, before
402 * the console is available.
403 */
404
405/*==========================================================================
406 * FSB Frequency detection
407 */
408
409/* These should be const but DT__AddProperty takes char* */
410static const char const TSC_Frequency_prop[] = "TSCFrequency";
411static const char const FSB_Frequency_prop[] = "FSBFrequency";
412static const char const CPU_Frequency_prop[] = "CPUFrequency";
413
414/*==========================================================================
415 * SMBIOS
416 */
417
418/* From Foundation/Efi/Guid/Smbios/SmBios.c */
419EFI_GUID constgEfiSmbiosTableGuid = EFI_SMBIOS_TABLE_GUID;
420
421#define SMBIOS_RANGE_START0x000F0000
422#define SMBIOS_RANGE_END0x000FFFFF
423
424/* '_SM_' in little endian: */
425#define SMBIOS_ANCHOR_UINT32_LE 0x5f4d535f
426
427#define EFI_ACPI_TABLE_GUID \
428 { \
4290xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, {0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
430 }
431
432#define EFI_ACPI_20_TABLE_GUID \
433 { \
4340x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, {0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \
435 }
436
437EFI_GUID gEfiAcpiTableGuid = EFI_ACPI_TABLE_GUID;
438EFI_GUID gEfiAcpi20TableGuid = EFI_ACPI_20_TABLE_GUID;
439
440
441/*==========================================================================
442 * Fake EFI implementation
443 */
444
445/* These should be const but DT__AddProperty takes char* */
446static const char const FIRMWARE_REVISION_PROP[] = "firmware-revision";
447static const char const FIRMWARE_ABI_PROP[] = "firmware-abi";
448static const char const FIRMWARE_VENDOR_PROP[] = "firmware-vendor";
449static const char const FIRMWARE_ABI_32_PROP_VALUE[] = "EFI32";
450static const char const FIRMWARE_ABI_64_PROP_VALUE[] = "EFI64";
451static const char const SYSTEM_ID_PROP[] = "system-id";
452static const char const SYSTEM_SERIAL_PROP[] = "SystemSerialNumber";
453static const char const SYSTEM_TYPE_PROP[] = "system-type";
454static const char const MODEL_PROP[] = "Model";
455//static const char const PLATFORM_UUID[] = "platform-uuid";
456
457
458/*
459 * Get an smbios option string option to convert to EFI_CHAR16 string
460 */
461
462static EFI_CHAR16* getSmbiosChar16(const char * key, size_t* len)
463{
464const char*src = getStringForKey(key, &bootInfo->smbiosConfig);
465EFI_CHAR16* dst = 0;
466size_t i = 0;
467
468if (!key || !(*key) || !len || !src) return 0;
469
470*len = strlen(src);
471dst = (EFI_CHAR16*) malloc( ((*len)+1) * 2 );
472for (; i < (*len); i++) dst[i] = src[i];
473dst[(*len)] = '\0';
474*len = ((*len)+1)*2; // return the CHAR16 bufsize including zero terminated CHAR16
475return dst;
476}
477
478/*
479 * Get the SystemID from the bios dmi info
480 */
481static EFI_GUID uuid;
482staticEFI_GUID * getSmbiosUUID()
483{
484int i, isZero, isOnes;
485//struct SMBEntryPoint*smbios;
486SMBByte*p, *u;
487//Slice - already done
488//smbios = getSmbios(SMBIOS_PATCHED); // checks for _SM_ anchor and table header checksum
489//if (smbios==NULL) return 0; // getSmbios() return a non null value if smbios is found
490
491p = (SMBByte*) FindFirstDmiTableOfType(1, 0x19); // Type 1: (3.3.2) System Information
492if (p==NULL) return NULL;
493p += 8;
494verbose("Found SMBIOS System Information Table 1\n");
495
496for (i=0, isZero=1, isOnes=1; i<UUID_LEN; i++)
497{
498if (p[i] != 0x00) isZero = 0;
499if (p[i] != 0xff) isOnes = 0;
500}
501
502if (isZero || isOnes) // empty or setable means: no uuid present
503{
504verbose("No UUID present in SMBIOS System Information Table\n");
505return 0;
506}
507
508//memcpy((void*)&uuid, p, UUID_LEN);
509//LE byte order while BE in SMBIOS
510u = (SMBByte *)&uuid;
511u[0] = p[3]; u[1] = p[2]; u[2] = p[1]; u[3] = p[0];
512u[4] = p[5]; u[5] = p[4]; u[6] = p[7]; u[7] = p[6];
513for (i=8; i<16; i++) {
514u[i] = p[i];
515}
516return &uuid;
517}
518
519/*
520 * return a binary UUID value from the overriden SystemID and SMUUID if found,
521 * or from the bios if not, or from a fixed value if no bios value is found
522 */
523
524extern EFI_GUID* getSystemID()
525{
526EFI_GUID*ret = NULL;
527// unable to determine UUID for host. Error: 35 fix
528// Rek: new SMsystemid option conforming to smbios notation standards, this option should
529// belong to smbios config only ...
530const char *sysId = getStringForKey(kSystemID, &bootInfo->bootConfig);
531if (sysId) {
532ret = (EFI_GUID*)getUUIDFromString(sysId);
533}
534
535if (!sysId || !ret) // try bios dmi info UUID extraction
536{
537ret = getSmbiosUUID();
538sysId = 0;
539}
540
541if (!ret) {
542// no bios dmi UUID available, set a fixed value for system-id
543//ret=getUUIDFromString((sysId = (const char*) SYSTEM_ID));
544ret = (EFI_GUID*)&SYSTEM_ID_DEFAULT;
545}
546#ifndef OPTION_ROM
547verbose("Customizing SystemID with : %s\n", getStringFromUUID(ret)); // apply a nice formatting to the displayed output
548#endif
549return ret;
550}
551/*
552 * Must be called AFTER setup Acpi because we need to take care of correct
553 * facp content to reflect in ioregs
554 */
555
556void setupSystemType()
557{
558Node *node = DT__FindNode("/", false);
559if (node == 0) stop("Couldn't get root node");
560// we need to write this property after facp parsing
561// Export system-type only if it has been overrriden by the SystemType option
562DT__AddProperty(node, SYSTEM_TYPE_PROP, sizeof(Platform->Type), &Platform->Type);
563}
564
565void setupEfiDeviceTree(void)
566{
567EFI_GUID*ret = 0;
568EFI_CHAR16* ret16 = 0;
569size_t len = 0;
570Node*node;
571
572node = DT__FindNode("/", false);
573
574if (node == 0) stop("Couldn't get root node");
575
576// We could also just do DT__FindNode("/efi/platform", true)
577// But I think eventually we want to fill stuff in the efi node
578// too so we might as well create it so we have a pointer for it too.
579node = DT__AddChild(node, "efi");
580
581if (archCpuType == CPU_TYPE_I386)
582{
583DT__AddProperty(node, FIRMWARE_ABI_PROP, sizeof(FIRMWARE_ABI_32_PROP_VALUE), (char*)FIRMWARE_ABI_32_PROP_VALUE);
584}
585else
586{
587DT__AddProperty(node, FIRMWARE_ABI_PROP, sizeof(FIRMWARE_ABI_64_PROP_VALUE), (char*)FIRMWARE_ABI_64_PROP_VALUE);
588}
589
590DT__AddProperty(node, FIRMWARE_REVISION_PROP, sizeof(FIRMWARE_REVISION), (EFI_UINT32*)&FIRMWARE_REVISION);
591DT__AddProperty(node, FIRMWARE_VENDOR_PROP, sizeof(FIRMWARE_VENDOR), (EFI_CHAR16*)FIRMWARE_VENDOR);
592
593// TODO: Fill in other efi properties if necessary
594
595// Set up the /efi/runtime-services table node similar to the way a child node of configuration-table
596// is set up. That is, name and table properties
597Node *runtimeServicesNode = DT__AddChild(node, "runtime-services");
598
599if (archCpuType == CPU_TYPE_I386)
600{
601// The value of the table property is the 32-bit physical address for the RuntimeServices table.
602// Since the EFI system table already has a pointer to it, we simply use the address of that pointer
603// for the pointer to the property data. Warning.. DT finalization calls free on that but we're not
604// the only thing to use a non-malloc'd pointer for something in the DT
605
606DT__AddProperty(runtimeServicesNode, "table", sizeof(uint64_t), &gST32->RuntimeServices);
607}
608else
609{
610DT__AddProperty(runtimeServicesNode, "table", sizeof(uint64_t), &gST64->RuntimeServices);
611}
612
613// Set up the /efi/configuration-table node which will eventually have several child nodes for
614// all of the configuration tables needed by various kernel extensions.
615gEfiConfigurationTableNode = DT__AddChild(node, "configuration-table");
616
617// Now fill in the /efi/platform Node
618Node *efiPlatformNode = DT__AddChild(node, "platform");
619
620// NOTE WELL: If you do add FSB Frequency detection, make sure to store
621// the value in the fsbFrequency global and not an malloc'd pointer
622// because the DT_AddProperty function does not copy its args.
623
624if (Platform->CPU.FSBFrequency != 0)
625DT__AddProperty(efiPlatformNode, FSB_Frequency_prop, sizeof(uint64_t), &Platform->CPU.FSBFrequency);
626
627// Export TSC and CPU frequencies for use by the kernel or KEXTs
628if (Platform->CPU.TSCFrequency != 0)
629DT__AddProperty(efiPlatformNode, TSC_Frequency_prop, sizeof(uint64_t), &Platform->CPU.TSCFrequency);
630
631if (Platform->CPU.CPUFrequency != 0)
632DT__AddProperty(efiPlatformNode, CPU_Frequency_prop, sizeof(uint64_t), &Platform->CPU.CPUFrequency);
633
634// Export system-id. Can be disabled with SystemId=No in com.apple.Boot.plist
635if ((ret=getSystemID()))
636DT__AddProperty(efiPlatformNode, SYSTEM_ID_PROP, UUID_LEN, (EFI_UINT32*) ret);
637
638 // Export SystemSerialNumber if present
639if ((ret16=getSmbiosChar16("SMserial", &len)))
640DT__AddProperty(efiPlatformNode, SYSTEM_SERIAL_PROP, len, ret16);
641
642// Export Model if present
643if ((ret16=getSmbiosChar16("SMproductname", &len)))
644DT__AddProperty(efiPlatformNode, MODEL_PROP, len, ret16);
645
646// Fill /efi/device-properties node.
647setupDeviceProperties(node);
648}
649
650/*
651 * Load the smbios.plist override config file if any
652 */
653
654static void setupSmbiosConfigFile(const char *filename)
655{
656chardirSpecSMBIOS[128] = "";
657const char *override_pathname = NULL;
658intlen = 0, err = 0;
659extern void scan_mem();
660
661// Take in account user overriding
662if (getValueForKey(kSMBIOSKey, &override_pathname, &len, &bootInfo->bootConfig) && len > 0)
663{
664// Specify a path to a file, e.g. SMBIOS=/Extra/macProXY.plist
665sprintf(dirSpecSMBIOS, override_pathname);
666err = loadConfigFile(dirSpecSMBIOS, &bootInfo->smbiosConfig);
667}
668else
669{
670// Check selected volume's Extra.
671sprintf(dirSpecSMBIOS, "/Extra/%s", filename);
672if (err = loadConfigFile(dirSpecSMBIOS, &bootInfo->smbiosConfig))
673{
674// Check booter volume/rdbt Extra.
675sprintf(dirSpecSMBIOS, "bt(0,0)/Extra/%s", filename);
676err = loadConfigFile(dirSpecSMBIOS, &bootInfo->smbiosConfig);
677}
678}
679
680if (err)
681{
682verbose("No SMBIOS replacement found.\n");
683}
684
685// get a chance to scan mem dynamically if user asks for it while having the config options loaded as well,
686// as opposed to when it was in scan_platform(); also load the orig. smbios so that we can access dmi info without
687// patching the smbios yet
688getSmbios(SMBIOS_ORIGINAL); //Slice - first encounter
689scan_mem();
690smbios_p = (EFI_PTR32)getSmbios(SMBIOS_PATCHED);// process smbios asap
691//Slice - no more getSMBIOS needed
692bool useDMIinfoCPU = true;
693 getBoolForKey(kUseCPUDMI, &useDMIinfoCPU, &bootInfo->bootConfig);
694if (useDMIinfoCPU) {
695scan_cpu_DMI(); //&Platform);
696}
697// PM_Model
698//if ((Platform->CPU.Features & CPU_FEATURE_MOBILE)) {
699if ((Platform->CPU.Mobile)) {
700Platform->Type = 2;
701} else {
702Platform->Type = 1;
703}
704
705//Slice - overclock CPU patch
706struct DMIProcessorInformation* p = (struct DMIProcessorInformation*) FindFirstDmiTableOfType(4, 0x28);
707
708if (useDMIinfoCPU && ((p->currentClock) &&
709//(p->currentClock > p->maximumClock) &&
710//(p->maximumClock != 3800) && (p->maximumClock != 4000) &&
711(p->currentClock < 10000)))
712{
713verbose("Overclocked CPU from %dMHz to %dMHz\n", p->maximumClock, p->currentClock);
714p->maximumClock = p->currentClock;
715Platform->CPU.TSCFrequency = p->currentClock * MEGA;
716}
717}
718
719/*
720 * Installs all the needed configuration table entries
721 */
722
723static void setupEfiConfigurationTable()
724{
725//smbios_p = (EFI_PTR32)getSmbios(SMBIOS_PATCHED); //cached
726addConfigurationTable(&gEfiSmbiosTableGuid, &smbios_p, NULL);
727
728// Setup ACPI with DSDT overrides (mackerintel's patch)
729//setupAcpi(); // in module
730
731// We've obviously changed the count.. so fix up the CRC32
732if (archCpuType == CPU_TYPE_I386)
733{
734gST32->Hdr.CRC32 = 0;
735gST32->Hdr.CRC32 = crc32(0L, gST32, gST32->Hdr.HeaderSize);
736}
737else
738{
739gST64->Hdr.CRC32 = 0;
740gST64->Hdr.CRC32 = crc32(0L, gST64, gST64->Hdr.HeaderSize);
741}
742}
743
744/*
745 * Entrypoint from boot.c
746 */
747
748void setupFakeEfi(void)
749{
750// Generate efi device strings
751//Slice - remember globals
752Platform = (PlatformInfo_t *)gPlatform;
753root_pci_dev = (pci_dt_t*)gRootPCIDev;
754
755//gBootOrder = (void*)BootOrder;
756
757//verbose("setupFakeEfi: root_pci_dev_Vendor=%04x\n", (root_pci_dev->children)->vendor_id);
758setup_pci_devs((pci_dt_t*)gRootPCIDev);
759
760// load smbios.plist file if any
761setupSmbiosConfigFile("SMBIOS.plist");
762
763// Initialize the base table
764if (archCpuType == CPU_TYPE_I386)
765{
766setupEfiTables32();
767}
768else
769{
770setupEfiTables64();
771}
772
773// Initialize the device tree
774setupEfiDeviceTree();
775
776//getSmbios(SMBIOS_ORIGINAL); //Slice - already done
777getSmbiosProductName();
778
779setupAcpi();
780//execute_hook("setupEfiConfigurationTable", NULL, NULL, NULL, NULL);
781
782// Add configuration table entries to both the services table and the device tree
783setupEfiConfigurationTable();
784addConfigurationTable(&gEfiSmbiosTableGuid, &smbios_p, NULL);
785if (archCpuType == CPU_TYPE_I386)
786{
787gST32->Hdr.CRC32 = 0;
788gST32->Hdr.CRC32 = crc32(0L, gST32, gST32->Hdr.HeaderSize);
789}
790else
791{
792gST64->Hdr.CRC32 = 0;
793gST64->Hdr.CRC32 = crc32(0L, gST64, gST64->Hdr.HeaderSize);
794}
795
796#if 1 //DEBUG
797struct DMIProcessorInformation* cpuInfo;
798struct DMIHeader * dmihdr;
799//Slice - Debug SMBIOS
800for (dmihdr = FindFirstDmiTableOfType(4, 30); dmihdr; dmihdr = FindNextDmiTableOfType(4, 30))
801{
802cpuInfo = (struct DMIProcessorInformation*)dmihdr;
803if (cpuInfo->processorType != 3) { // CPU
804continue;
805}
806//TODO validate
807//msglog("Patched platform CPU Info:\n FSB=%d\n MaxSpeed=%d\n CurrentSpeed=%d\n",
808// Platform->CPU.FSBFrequency/MEGA, Platform->CPU.TSCFrequency/MEGA, Platform->CPU.CPUFrequency/MEGA);
809
810msglog("Patched SMBIOS CPU Info:\n FSB=%d\n MaxSpeed=%d\n CurrentSpeed=%d\n", cpuInfo->externalClock, cpuInfo->maximumClock, cpuInfo->currentClock);
811msglog(" Family=%x Socket=%x\n Cores=%d Enabled=%d Threads=%d\n", cpuInfo->processorFamily, cpuInfo->processorUpgrade, cpuInfo->coreCount, cpuInfo->coreEnabled, cpuInfo->Threads);
812}
813#endif
814}
815
816

Archive Download this file

Revision: 1174