:: limine / common / protos / linux_x86.c 23.0 KB raw

1
#if defined (__x86_64__) || defined (__i386__)
2
3
#include <stdint.h>
4
#include <stddef.h>
5
#include <stdnoreturn.h>
6
#include <protos/linux.h>
7
#include <fs/file.h>
8
#include <lib/libc.h>
9
#include <lib/misc.h>
10
#include <lib/real.h>
11
#include <lib/term.h>
12
#include <lib/config.h>
13
#include <lib/print.h>
14
#include <lib/uri.h>
15
#include <lib/tpm.h>
16
#include <mm/pmm.h>
17
#include <sys/idt.h>
18
#include <lib/fb.h>
19
#include <lib/acpi.h>
20
#include <sys/iommu.h>
21
#include <drivers/edid.h>
22
#include <drivers/vga_textmode.h>
23
#include <drivers/gop.h>
24
25
noreturn void linux_spinup(void *entry, void *boot_params);
26
#if defined (UEFI) && defined (__x86_64__)
27
    noreturn void linux_spinup64(void *entry, void *boot_params);
28
#endif
29
30
// The following definitions and struct were copied and adapted from Linux
31
// kernel headers released under GPL-2.0 WITH Linux-syscall-note
32
// allowing their inclusion in non GPL compliant code.
33
34
#define EDD_MBR_SIG_MAX 16
35
#define E820_MAX_ENTRIES_ZEROPAGE 128
36
#define EDDMAXNR 6
37
38
struct setup_header {
39
    uint8_t    setup_sects;
40
    uint16_t    root_flags;
41
    uint32_t    syssize;
42
    uint16_t    ram_size;
43
    uint16_t    vid_mode;
44
    uint16_t    root_dev;
45
    uint16_t    boot_flag;
46
    uint16_t    jump;
47
    uint32_t    header;
48
    uint16_t    version;
49
    uint32_t    realmode_swtch;
50
    uint16_t    start_sys_seg;
51
    uint16_t    kernel_version;
52
    uint8_t    type_of_loader;
53
    uint8_t    loadflags;
54
    uint16_t    setup_move_size;
55
    uint32_t    code32_start;
56
    uint32_t    ramdisk_image;
57
    uint32_t    ramdisk_size;
58
    uint32_t    bootsect_kludge;
59
    uint16_t    heap_end_ptr;
60
    uint8_t    ext_loader_ver;
61
    uint8_t    ext_loader_type;
62
    uint32_t    cmd_line_ptr;
63
    uint32_t    initrd_addr_max;
64
    uint32_t    kernel_alignment;
65
    uint8_t    relocatable_kernel;
66
    uint8_t    min_alignment;
67
    uint16_t    xloadflags;
68
    uint32_t    cmdline_size;
69
    uint32_t    hardware_subarch;
70
    uint64_t    hardware_subarch_data;
71
    uint32_t    payload_offset;
72
    uint32_t    payload_length;
73
    uint64_t    setup_data;
74
    uint64_t    pref_address;
75
    uint32_t    init_size;
76
    uint32_t    handover_offset;
77
    uint32_t    kernel_info_offset;
78
} __attribute__((packed));
79
80
struct apm_bios_info {
81
    uint16_t    version;
82
    uint16_t    cseg;
83
    uint32_t    offset;
84
    uint16_t    cseg_16;
85
    uint16_t    dseg;
86
    uint16_t    flags;
87
    uint16_t    cseg_len;
88
    uint16_t    cseg_16_len;
89
    uint16_t    dseg_len;
90
};
91
92
struct ist_info {
93
    uint32_t signature;
94
    uint32_t command;
95
    uint32_t event;
96
    uint32_t perf_level;
97
};
98
99
struct sys_desc_table {
100
    uint16_t length;
101
    uint8_t  table[14];
102
};
103
104
struct olpc_ofw_header {
105
    uint32_t ofw_magic;    /* OFW signature */
106
    uint32_t ofw_version;
107
    uint32_t cif_handler;    /* callback into OFW */
108
    uint32_t irq_desc_table;
109
} __attribute__((packed));
110
111
struct edid_info {
112
    unsigned char dummy[128];
113
};
114
115
struct efi_info {
116
    uint32_t efi_loader_signature;
117
    uint32_t efi_systab;
118
    uint32_t efi_memdesc_size;
119
    uint32_t efi_memdesc_version;
120
    uint32_t efi_memmap;
121
    uint32_t efi_memmap_size;
122
    uint32_t efi_systab_hi;
123
    uint32_t efi_memmap_hi;
124
};
125
126
struct boot_e820_entry {
127
    uint64_t addr;
128
    uint64_t size;
129
    uint32_t type;
130
} __attribute__((packed));
131
132
struct edd_device_params {
133
    uint16_t length;
134
    uint16_t info_flags;
135
    uint32_t num_default_cylinders;
136
    uint32_t num_default_heads;
137
    uint32_t sectors_per_track;
138
    uint64_t number_of_sectors;
139
    uint16_t bytes_per_sector;
140
    uint32_t dpte_ptr;        /* 0xFFFFFFFF for our purposes */
141
    uint16_t key;        /* = 0xBEDD */
142
    uint8_t device_path_info_length;    /* = 44 */
143
    uint8_t reserved2;
144
    uint16_t reserved3;
145
    uint8_t host_bus_type[4];
146
    uint8_t interface_type[8];
147
    union {
148
        struct {
149
            uint16_t base_address;
150
            uint16_t reserved1;
151
            uint32_t reserved2;
152
        } __attribute__ ((packed)) isa;
153
        struct {
154
            uint8_t bus;
155
            uint8_t slot;
156
            uint8_t function;
157
            uint8_t channel;
158
            uint32_t reserved;
159
        } __attribute__ ((packed)) pci;
160
        /* pcix is same as pci */
161
        struct {
162
            uint64_t reserved;
163
        } __attribute__ ((packed)) ibnd;
164
        struct {
165
            uint64_t reserved;
166
        } __attribute__ ((packed)) xprs;
167
        struct {
168
            uint64_t reserved;
169
        } __attribute__ ((packed)) htpt;
170
        struct {
171
            uint64_t reserved;
172
        } __attribute__ ((packed)) unknown;
173
    } interface_path;
174
    union {
175
        struct {
176
            uint8_t device;
177
            uint8_t reserved1;
178
            uint16_t reserved2;
179
            uint32_t reserved3;
180
            uint64_t reserved4;
181
        } __attribute__ ((packed)) ata;
182
        struct {
183
            uint8_t device;
184
            uint8_t lun;
185
            uint8_t reserved1;
186
            uint8_t reserved2;
187
            uint32_t reserved3;
188
            uint64_t reserved4;
189
        } __attribute__ ((packed)) atapi;
190
        struct {
191
            uint16_t id;
192
            uint64_t lun;
193
            uint16_t reserved1;
194
            uint32_t reserved2;
195
        } __attribute__ ((packed)) scsi;
196
        struct {
197
            uint64_t serial_number;
198
            uint64_t reserved;
199
        } __attribute__ ((packed)) usb;
200
        struct {
201
            uint64_t eui;
202
            uint64_t reserved;
203
        } __attribute__ ((packed)) i1394;
204
        struct {
205
            uint64_t wwid;
206
            uint64_t lun;
207
        } __attribute__ ((packed)) fibre;
208
        struct {
209
            uint64_t identity_tag;
210
            uint64_t reserved;
211
        } __attribute__ ((packed)) i2o;
212
        struct {
213
            uint32_t array_number;
214
            uint32_t reserved1;
215
            uint64_t reserved2;
216
        } __attribute__ ((packed)) raid;
217
        struct {
218
            uint8_t device;
219
            uint8_t reserved1;
220
            uint16_t reserved2;
221
            uint32_t reserved3;
222
            uint64_t reserved4;
223
        } __attribute__ ((packed)) sata;
224
        struct {
225
            uint64_t reserved1;
226
            uint64_t reserved2;
227
        } __attribute__ ((packed)) unknown;
228
    } device_path;
229
    uint8_t reserved4;
230
    uint8_t checksum;
231
} __attribute__ ((packed));
232
233
struct edd_info {
234
    uint8_t device;
235
    uint8_t version;
236
    uint16_t interface_support;
237
    uint16_t legacy_max_cylinder;
238
    uint8_t legacy_max_head;
239
    uint8_t legacy_sectors_per_track;
240
    struct edd_device_params params;
241
} __attribute__ ((packed));
242
243
struct boot_params {
244
    struct screen_info screen_info;            /* 0x000 */
245
    struct apm_bios_info apm_bios_info;        /* 0x040 */
246
    uint8_t  _pad2[4];                    /* 0x054 */
247
    uint64_t  tboot_addr;                /* 0x058 */
248
    struct ist_info ist_info;            /* 0x060 */
249
    uint64_t acpi_rsdp_addr;                /* 0x070 */
250
    uint8_t  _pad3[8];                    /* 0x078 */
251
    uint8_t  hd0_info[16];    /* obsolete! */        /* 0x080 */
252
    uint8_t  hd1_info[16];    /* obsolete! */        /* 0x090 */
253
    struct sys_desc_table sys_desc_table; /* obsolete! */    /* 0x0a0 */
254
    struct olpc_ofw_header olpc_ofw_header;        /* 0x0b0 */
255
    uint32_t ext_ramdisk_image;            /* 0x0c0 */
256
    uint32_t ext_ramdisk_size;                /* 0x0c4 */
257
    uint32_t ext_cmd_line_ptr;                /* 0x0c8 */
258
    uint8_t  _pad4[116];                /* 0x0cc */
259
    struct edid_info edid_info;            /* 0x140 */
260
    struct efi_info efi_info;            /* 0x1c0 */
261
    uint32_t alt_mem_k;                /* 0x1e0 */
262
    uint32_t scratch;        /* Scratch field! */    /* 0x1e4 */
263
    uint8_t  e820_entries;                /* 0x1e8 */
264
    uint8_t  eddbuf_entries;                /* 0x1e9 */
265
    uint8_t  edd_mbr_sig_buf_entries;            /* 0x1ea */
266
    uint8_t  kbd_status;                /* 0x1eb */
267
    uint8_t  secure_boot;                /* 0x1ec */
268
    uint8_t  _pad5[2];                    /* 0x1ed */
269
    /*
270
     * The sentinel is set to a nonzero value (0xff) in header.S.
271
     *
272
     * A bootloader is supposed to only take setup_header and put
273
     * it into a clean boot_params buffer. If it turns out that
274
     * it is clumsy or too generous with the buffer, it most
275
     * probably will pick up the sentinel variable too. The fact
276
     * that this variable then is still 0xff will let kernel
277
     * know that some variables in boot_params are invalid and
278
     * kernel should zero out certain portions of boot_params.
279
     */
280
    uint8_t  sentinel;                    /* 0x1ef */
281
    uint8_t  _pad6[1];                    /* 0x1f0 */
282
    struct setup_header hdr;    /* setup header */    /* 0x1f1 */
283
    uint8_t  _pad7[0x290-0x1f1-sizeof(struct setup_header)];
284
    uint32_t edd_mbr_sig_buffer[EDD_MBR_SIG_MAX];    /* 0x290 */
285
    struct boot_e820_entry e820_table[E820_MAX_ENTRIES_ZEROPAGE]; /* 0x2d0 */
286
    uint8_t  _pad8[48];                /* 0xcd0 */
287
    struct edd_info eddbuf[EDDMAXNR];        /* 0xd00 */
288
    uint8_t  _pad9[276];                /* 0xeec */
289
} __attribute__((packed));
290
291
// End of Linux code
292
293
noreturn void linux_load(char *config, char *cmdline) {
294
    struct file_handle *kernel_file;
295
296
#if defined (UEFI)
297
    if (cmdline != NULL) {
298
        tpm_measure(TPM_PCR_BOOT_AUTH, TPM_EV_IPL,
299
                    cmdline, strlen(cmdline), "cmdline: ", cmdline);
300
    }
301
#endif
302
303
    char *kernel_path = config_get_value(config, 0, "PATH");
304
    if (kernel_path == NULL) {
305
        kernel_path = config_get_value(config, 0, "KERNEL_PATH");
306
    }
307
    if (kernel_path == NULL) {
308
        panic(true, "linux: Kernel path not specified");
309
    }
310
311
    print("linux: Loading kernel `%#`...\n", kernel_path);
312
313
    if ((kernel_file = uri_open(kernel_path, MEMMAP_BOOTLOADER_RECLAIMABLE, false
314
#if defined (__i386__)
315
        , NULL, NULL
316
#endif
317
    )) == NULL)
318
        panic(true, "linux: Failed to open kernel with path `%#`. Is the path correct?", kernel_path);
319
320
    // Minimum size check: need at least 0x206 bytes for signature at 0x202
321
    if (kernel_file->size < 0x206) {
322
        panic(true, "linux: Kernel file too small");
323
    }
324
325
#if defined (UEFI) && defined (__x86_64__)
326
    bool use_64_bit_proto = false;
327
#endif
328
329
    uint32_t signature;
330
    fread(kernel_file, &signature, 0x202, sizeof(uint32_t));
331
332
    // validate signature
333
    if (signature != 0x53726448) {
334
        panic(true, "linux: Invalid kernel signature");
335
    }
336
337
    size_t setup_code_size = 0;
338
    fread(kernel_file, &setup_code_size, 0x1f1, 1);
339
340
    if (setup_code_size == 0)
341
        setup_code_size = 4;
342
343
    setup_code_size *= 512;
344
345
    size_t real_mode_code_size = 512 + setup_code_size;
346
347
    if (real_mode_code_size > kernel_file->size) {
348
        panic(true, "linux: Kernel file too small for real mode code");
349
    }
350
351
    struct boot_params *boot_params = ext_mem_alloc(sizeof(struct boot_params));
352
353
    struct setup_header *setup_header = &boot_params->hdr;
354
355
    size_t setup_header_end = ({
356
        uint8_t x;
357
        fread(kernel_file, &x, 0x201, 1);
358
        0x202 + x;
359
    });
360
361
    if (setup_header_end > kernel_file->size) {
362
        panic(true, "linux: Kernel file too small for setup header");
363
    }
364
365
    fread(kernel_file, setup_header, 0x1f1, setup_header_end - 0x1f1);
366
367
    printv("linux: Boot protocol: %u.%u\n",
368
           setup_header->version >> 8, setup_header->version & 0xff);
369
370
    if (setup_header->version < 0x203) {
371
        panic(true, "linux: Protocols < 2.03 are not supported");
372
    }
373
374
    setup_header->cmd_line_ptr = (uint32_t)(uintptr_t)cmdline;
375
376
    // vid_mode. 0xffff means "normal"
377
    setup_header->vid_mode = 0xffff;
378
379
    if (verbose) {
380
        char *kernel_version = ext_mem_alloc(128);
381
        if (setup_header->kernel_version != 0) {
382
            size_t version_offset = (size_t)setup_header->kernel_version + 0x200;
383
            if (version_offset + 128 <= kernel_file->size) {
384
                fread(kernel_file, kernel_version, version_offset, 128);
385
                kernel_version[127] = '\0';
386
                print("linux: Kernel version: %s\n", kernel_version);
387
            }
388
        }
389
        pmm_free(kernel_version, 128);
390
    }
391
392
    setup_header->type_of_loader = 0xff;
393
394
    if (!(setup_header->loadflags & (1 << 0))) {
395
        panic(true, "linux: Kernels that load at 0x10000 are not supported");
396
    }
397
398
    setup_header->loadflags &= ~(1 << 5);     // print early messages
399
400
    // load kernel
401
    size_t kernel_data_size = kernel_file->size - real_mode_code_size;
402
    size_t kernel_alloc_size = kernel_data_size;
403
    if (setup_header->version >= 0x20a && setup_header->init_size > kernel_alloc_size) {
404
        kernel_alloc_size = setup_header->init_size;
405
    }
406
    uintptr_t kernel_align = 0x100000;
407
    if (setup_header->version >= 0x205 && setup_header->kernel_alignment > kernel_align) {
408
        kernel_align = setup_header->kernel_alignment;
409
    }
410
    // Start at pref_address: the decompressor relocates itself up to
411
    // LOAD_PHYSICAL_ADDR (= pref_address) and scribbles init_size bytes from
412
    // there, so loading below it would leave that range unreserved.
413
    uintptr_t kernel_search_start = 0x100000;
414
    if (setup_header->version >= 0x20a
415
     && setup_header->pref_address >= 0x100000
416
     && setup_header->pref_address + (uint64_t)kernel_alloc_size <= UINTPTR_MAX) {
417
        kernel_search_start = (uintptr_t)setup_header->pref_address;
418
    }
419
    // Non-relocatable kernels must be loaded at their required address; do
420
    // not step up on failure.
421
    bool relocatable_kernel = setup_header->version >= 0x205
422
                           && setup_header->relocatable_kernel != 0;
423
    uintptr_t kernel_load_addr = ALIGN_UP(kernel_search_start, kernel_align, panic(true, "linux: Alignment overflow"));
424
    for (;;) {
425
        if (memmap_alloc_range(kernel_load_addr,
426
                ALIGN_UP(kernel_alloc_size, 4096, panic(true, "linux: Alignment overflow")),
427
                MEMMAP_BOOTLOADER_RECLAIMABLE, MEMMAP_USABLE, false, false, false))
428
            break;
429
430
        if (!relocatable_kernel) {
431
            panic(true, "linux: Non-relocatable kernel could not be loaded at required address %X", (uint64_t)kernel_load_addr);
432
        }
433
434
        if (kernel_load_addr >= 0xfff00000) {
435
            panic(true, "linux: Failed to allocate memory for kernel");
436
        }
437
438
        kernel_load_addr += kernel_align;
439
    }
440
441
    fread(kernel_file, (void *)kernel_load_addr, real_mode_code_size, kernel_file->size - real_mode_code_size);
442
443
#if defined (UEFI)
444
    tpm_measure_path(TPM_PCR_BOOT_AUTH, TPM_EV_IPL, "path: ", kernel_path);
445
    tpm_measure(TPM_PCR_LOADED_IMAGES, TPM_EV_IPL,
446
                kernel_file->fd, kernel_file->size, "path: ", kernel_path);
447
#endif
448
449
    fclose(kernel_file);
450
451
    ///////////////////////////////////////
452
    // Modules
453
    ///////////////////////////////////////
454
    size_t size_of_all_modules = 0;
455
456
    size_t module_count;
457
    for (module_count = 0; ; module_count++) {
458
        char *module_path = config_get_value(config, module_count, "MODULE_PATH");
459
        if (module_path == NULL)
460
            break;
461
    }
462
463
    if (module_count == 0) {
464
        goto no_modules;
465
    }
466
467
    struct file_handle **modules = ext_mem_alloc_counted(module_count, sizeof(struct file_handle *));
468
469
    for (size_t i = 0; ; i++) {
470
        char *module_path = config_get_value(config, i, "MODULE_PATH");
471
        if (module_path == NULL)
472
            break;
473
474
        print("linux: Loading module `%#`...\n", module_path);
475
476
        struct file_handle *module;
477
        if ((module = uri_open(module_path, MEMMAP_BOOTLOADER_RECLAIMABLE, false
478
#if defined (__i386__)
479
            , NULL, NULL
480
#endif
481
        )) == NULL)
482
            panic(true, "linux: Failed to open module with path `%s`. Is the path correct?", module_path);
483
484
        size_of_all_modules = CHECKED_ADD(size_of_all_modules, module->size,
485
            panic(true, "linux: Total module size overflow"));
486
487
        modules[i] = module;
488
    }
489
490
    uint64_t modules_mem_base;
491
492
    if (setup_header->version <= 0x202 || setup_header->initrd_addr_max == 0) {
493
        modules_mem_base = 0x38000000;
494
    } else {
495
        modules_mem_base = (uint64_t)setup_header->initrd_addr_max + 1;
496
    }
497
498
    if (size_of_all_modules > modules_mem_base) {
499
        panic(true, "linux: Total module size exceeds available address space");
500
    }
501
    modules_mem_base -= size_of_all_modules;
502
    modules_mem_base = ALIGN_DOWN(modules_mem_base, 0x100000);
503
504
    for (;;) {
505
        if (modules_mem_base < 0x100000) {
506
#if defined (UEFI) && defined (__x86_64__)
507
            if ((setup_header->xloadflags & 3) == 3) {
508
                modules_mem_base = (uintptr_t)ext_mem_alloc_type_aligned_mode(
509
                    size_of_all_modules,
510
                    MEMMAP_BOOTLOADER_RECLAIMABLE,
511
                    0x200000,
512
                    true
513
                );
514
                use_64_bit_proto = true;
515
                break;
516
            }
517
#endif
518
            panic(true, "linux: Failed to allocate memory for modules");
519
        }
520
521
        if (memmap_alloc_range(modules_mem_base, ALIGN_UP(size_of_all_modules, 0x100000, panic(true, "linux: Alignment overflow")),
522
                               MEMMAP_BOOTLOADER_RECLAIMABLE, MEMMAP_USABLE, false, false, false))
523
            break;
524
525
        modules_mem_base -= 0x100000;
526
    }
527
528
    uintptr_t _modules_mem_base = modules_mem_base;
529
    for (size_t i = 0; ; i++) {
530
        char *module_path = config_get_value(config, i, "MODULE_PATH");
531
        if (module_path == NULL)
532
            break;
533
534
        fread(modules[i], (void *)_modules_mem_base, 0, modules[i]->size);
535
536
#if defined (UEFI)
537
        tpm_measure_path(TPM_PCR_BOOT_AUTH, TPM_EV_IPL, "module_path: ", module_path);
538
        tpm_measure(TPM_PCR_LOADED_IMAGES, TPM_EV_IPL,
539
                    (void *)_modules_mem_base, modules[i]->size, "module_path: ", module_path);
540
#endif
541
542
        _modules_mem_base += modules[i]->size;
543
544
        fclose(modules[i]);
545
    }
546
547
    pmm_free(modules, module_count * sizeof(struct file_handle *));
548
549
    setup_header->ramdisk_image = (uint32_t)modules_mem_base;
550
#if defined (UEFI) && defined (__x86_64__)
551
    boot_params->ext_ramdisk_image = (uint32_t)(modules_mem_base >> 32);
552
#endif
553
    setup_header->ramdisk_size = (uint32_t)size_of_all_modules;
554
#if defined (UEFI) && defined (__x86_64__)
555
    boot_params->ext_ramdisk_size = (uint32_t)(size_of_all_modules >> 32);
556
#endif
557
558
no_modules:;
559
560
    ///////////////////////////////////////
561
    // Video
562
    ///////////////////////////////////////
563
564
    term_notready();
565
566
    struct screen_info *screen_info = &boot_params->screen_info;
567
568
#if defined (BIOS)
569
    {
570
    char *textmode_str = config_get_value(config, 0, "TEXTMODE");
571
    bool textmode = textmode_str != NULL && strcmp(textmode_str, "yes") == 0;
572
    if (textmode) {
573
        goto set_textmode;
574
    }
575
    }
576
#endif
577
578
    size_t req_width = 0, req_height = 0, req_bpp = 0;
579
580
    char *resolution = config_get_value(config, 0, "RESOLUTION");
581
    if (resolution != NULL)
582
        parse_resolution(&req_width, &req_height, &req_bpp, resolution);
583
584
    struct fb_info *fbs;
585
    size_t fbs_count;
586
#if defined (UEFI)
587
    gop_force_16 = true;
588
#endif
589
    fb_init(&fbs, &fbs_count, req_width, req_height, req_bpp, false, false);
590
    if (fbs_count == 0) {
591
#if defined (UEFI)
592
        goto no_fb;
593
#elif defined (BIOS)
594
set_textmode:;
595
        vga_textmode_init(false);
596
597
        screen_info->orig_video_mode = 3;
598
        screen_info->orig_video_ega_bx = 3;
599
        screen_info->orig_video_lines = 25;
600
        screen_info->orig_video_cols = 80;
601
        screen_info->orig_video_points = 16;
602
603
        screen_info->orig_video_isVGA = VIDEO_TYPE_VGAC;
604
#endif
605
    } else {
606
        screen_info->capabilities   = VIDEO_CAPABILITY_64BIT_BASE | VIDEO_CAPABILITY_SKIP_QUIRKS;
607
        screen_info->flags          = VIDEO_FLAGS_NOCURSOR;
608
        screen_info->lfb_base       = (uint32_t)fbs[0].framebuffer_addr;
609
        screen_info->ext_lfb_base   = (uint32_t)(fbs[0].framebuffer_addr >> 32);
610
        screen_info->lfb_size       = fbs[0].framebuffer_pitch * fbs[0].framebuffer_height;
611
        screen_info->lfb_width      = fbs[0].framebuffer_width;
612
        screen_info->lfb_height     = fbs[0].framebuffer_height;
613
        screen_info->lfb_depth      = fbs[0].framebuffer_bpp;
614
        screen_info->lfb_linelength = fbs[0].framebuffer_pitch;
615
        screen_info->red_size       = fbs[0].red_mask_size;
616
        screen_info->red_pos        = fbs[0].red_mask_shift;
617
        screen_info->green_size     = fbs[0].green_mask_size;
618
        screen_info->green_pos      = fbs[0].green_mask_shift;
619
        screen_info->blue_size      = fbs[0].blue_mask_size;
620
        screen_info->blue_pos       = fbs[0].blue_mask_shift;
621
622
        if (fbs[0].edid != NULL) {
623
            memcpy(&boot_params->edid_info, fbs[0].edid, sizeof(struct edid_info_struct));
624
        }
625
626
#if defined (BIOS)
627
        screen_info->orig_video_isVGA = VIDEO_TYPE_VLFB;
628
        screen_info->lfb_size = DIV_ROUNDUP(screen_info->lfb_size, 65536, panic(true, "linux: Alignment overflow"));
629
#elif defined (UEFI)
630
        screen_info->orig_video_isVGA = VIDEO_TYPE_EFI;
631
#endif
632
    }
633
634
#if defined (UEFI)
635
no_fb:;
636
#endif
637
    ///////////////////////////////////////
638
    // RSDP
639
    ///////////////////////////////////////
640
641
    boot_params->acpi_rsdp_addr = (uintptr_t)acpi_get_rsdp();
642
643
    ///////////////////////////////////////
644
    // UEFI
645
    ///////////////////////////////////////
646
#if defined (UEFI)
647
    linux_install_efi_tpm_event_log();
648
    efi_exit_boot_services();
649
650
#if defined (__x86_64__)
651
    memcpy(&boot_params->efi_info.efi_loader_signature, "EL64", 4);
652
#elif defined (__i386__)
653
    memcpy(&boot_params->efi_info.efi_loader_signature, "EL32", 4);
654
#endif
655
656
    boot_params->efi_info.efi_systab    = (uint32_t)(uint64_t)(uintptr_t)gST;
657
    boot_params->efi_info.efi_systab_hi = (uint32_t)((uint64_t)(uintptr_t)gST >> 32);
658
    boot_params->efi_info.efi_memmap    = (uint32_t)(uint64_t)(uintptr_t)efi_mmap;
659
    boot_params->efi_info.efi_memmap_hi = (uint32_t)((uint64_t)(uintptr_t)efi_mmap >> 32);
660
    boot_params->efi_info.efi_memmap_size     = efi_mmap_size;
661
    boot_params->efi_info.efi_memdesc_size    = efi_desc_size;
662
    boot_params->efi_info.efi_memdesc_version = efi_desc_ver;
663
664
    boot_params->secure_boot = secure_boot_active ? 3 : 2;
665
#endif
666
667
    ///////////////////////////////////////
668
    // e820
669
    ///////////////////////////////////////
670
671
    struct boot_e820_entry *e820_table = boot_params->e820_table;
672
673
    size_t mmap_entries;
674
    struct memmap_entry *mmap = get_raw_memmap(&mmap_entries);
675
676
    for (size_t i = 0, j = 0; i < mmap_entries; i++) {
677
        if (mmap[i].type >= 0x1000) {
678
            continue;
679
        }
680
        if (j >= E820_MAX_ENTRIES_ZEROPAGE) {
681
            panic(false, "linux: Too many E820 memory map entries");
682
        }
683
        e820_table[j].addr = mmap[i].base;
684
        e820_table[j].size = mmap[i].length;
685
        e820_table[j].type = mmap[i].type;
686
        j++;
687
        boot_params->e820_entries = j;
688
    }
689
690
    ///////////////////////////////////////
691
    // Spin up
692
    ///////////////////////////////////////
693
694
    // Commented out because Linux shouldn't need it and we don't want to
695
    // introduce potential breakages or security weakening.
696
    //iommu_disable_all();
697
698
    irq_flush_type = IRQ_PIC_ONLY_FLUSH;
699
700
#if defined (UEFI) && defined (__x86_64__)
701
    if (use_64_bit_proto == true && (setup_header->xloadflags & 3) == 3) {
702
        flush_irqs();
703
        linux_spinup64((void *)kernel_load_addr + 0x200, boot_params);
704
    }
705
#endif
706
707
    common_spinup(linux_spinup, 2, (uint32_t)kernel_load_addr,
708
                                   (uint32_t)(uintptr_t)boot_params);
709
}
710
711
#endif
tab: 248 wrap: offon