:: limine / common / entry.s2.c 3.1 KB raw

1
#include <stddef.h>
2
#include <stdint.h>
3
#include <stdbool.h>
4
#include <stdnoreturn.h>
5
#include <lib/term.h>
6
#include <lib/real.h>
7
#include <lib/misc.h>
8
#include <lib/libc.h>
9
#include <lib/part.h>
10
#include <lib/config.h>
11
#include <lib/trace.h>
12
#include <sys/e820.h>
13
#include <sys/a20.h>
14
#include <lib/print.h>
15
#include <fs/file.h>
16
#include <lib/elf.h>
17
#include <mm/pmm.h>
18
#include <protos/linux.h>
19
#include <protos/chainload.h>
20
#include <menu.h>
21
#include <pxe/pxe.h>
22
#include <pxe/tftp.h>
23
#include <drivers/disk.h>
24
#include <sys/idt.h>
25
#include <sys/cpu.h>
26
27
struct volume *boot_volume;
28
29
#if defined (BIOS)
30
31
bool stage3_loaded = false;
32
static bool stage3_found = false;
33
34
extern symbol stage3_addr;
35
extern symbol limine_bios_sys_size;
36
extern symbol build_id_s2;
37
extern symbol build_id_s3;
38
39
static bool stage3_init(struct volume *part) {
40
    struct file_handle *stage3;
41
42
    bool old_cif = case_insensitive_fopen;
43
    case_insensitive_fopen = true;
44
    if (true
45
     && (stage3 = fopen(part, "/boot/limine/limine-bios.sys")) == NULL
46
     && (stage3 = fopen(part, "/boot/limine-bios.sys")) == NULL
47
     && (stage3 = fopen(part, "/limine/limine-bios.sys")) == NULL
48
     && (stage3 = fopen(part, "/limine-bios.sys")) == NULL
49
    ) {
50
        case_insensitive_fopen = old_cif;
51
        return false;
52
    }
53
    case_insensitive_fopen = old_cif;
54
55
    stage3_found = true;
56
57
    if (stage3->size != (size_t)limine_bios_sys_size) {
58
        print("limine-bios.sys size incorrect.\n");
59
        return false;
60
    }
61
62
    fread(stage3, stage3_addr,
63
          (uintptr_t)stage3_addr - 0xf000,
64
          stage3->size - ((uintptr_t)stage3_addr - 0xf000));
65
66
    fclose(stage3);
67
68
    if (memcmp(build_id_s2 + 16, build_id_s3 + 16, 20) != 0) {
69
        print("limine-bios.sys build ID mismatch.\n");
70
        return false;
71
    }
72
73
    stage3_loaded = true;
74
75
    return true;
76
}
77
78
enum {
79
    BOOTED_FROM_HDD = 0,
80
    BOOTED_FROM_PXE = 1,
81
    BOOTED_FROM_CD = 2
82
};
83
84
noreturn void entry(uint8_t boot_drive, int boot_from) {
85
    // XXX DO NOT MOVE A20 ENABLE CALL
86
    if (!a20_enable()) {
87
        panic(false, "Could not enable A20 line");
88
    }
89
90
    calibrate_tsc();
91
    uint64_t usec_at_entry = rdtsc_usec();
92
93
    init_e820();
94
    init_memmap();
95
96
    init_idt();
97
98
    disk_create_index();
99
100
    if (boot_from == BOOTED_FROM_HDD || boot_from == BOOTED_FROM_CD) {
101
        boot_volume = volume_get_by_bios_drive(boot_drive);
102
    } else if (boot_from == BOOTED_FROM_PXE) {
103
        pxe_init();
104
        boot_volume = pxe_bind_volume();
105
    }
106
107
    if (boot_volume == NULL) {
108
        panic(false, "Could not determine boot drive");
109
    }
110
111
    volume_iterate_parts(boot_volume,
112
        if (stage3_init(_PART)) {
113
            break;
114
        }
115
    );
116
117
    if (!stage3_found) {
118
        print("\n"
119
              "!! Stage 3 file not found!\n"
120
              "!! Have you copied limine-bios.sys to the root, /boot, /limine, or /boot/limine\n"
121
              "!! directories of one of the partitions on the boot device?\n\n");
122
    }
123
124
    if (!stage3_loaded) {
125
        panic(false, "Failed to load stage 3.");
126
    }
127
128
    term_fallback();
129
130
    usec_at_bootloader_entry = usec_at_entry;
131
    stage3_common();
132
}
133
134
#endif
tab: 248 wrap: offon