Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 1146