Chameleon

Chameleon Commit Details

Date:2010-08-30 16:39:38 (13 years 8 months ago)
Author:Tamás Kosárszky
Commit:450
Parents: 449
Message:Applied Azimutz's fake_efi changes for setting up EFI32/64 system tables.
Changes:
M/trunk/i386/libsaio/fake_efi.c
M/trunk/i386/boot2/boot.h
M/trunk/i386/libsaio/fake_efi.h

File differences

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

Archive Download the corresponding diff file

Revision: 450