1 /*
2  * Multiboot C Entry
3  */
4 
5 #include <stdbool.h>
6 #include <stdint.h>
7 
8 #include <sys/kassert.h>
9 #include <sys/cdefs.h>
10 
11 #include "../dev/console.h"
12 
13 #include <machine/amd64.h>
14 #include <machine/pmap.h>
15 #include <machine/multiboot.h>
16 
17 void MachineBoot_Entry(unsigned long magic, unsigned long addr);
18 
19 #define CHECK_FLAG(flag, bit) ((flag) & (1 << (bit)))
20 
21 #define PAGE_ALIGN __attribute__((aligned(PGSIZE)))
22 #define DATA_SECTION __attribute__((section(".data")))
23 
24 extern void Machine_EarlyInit();
25 extern void Machine_Init();
26 extern void PAlloc_AddRegion(uintptr_t start, uintptr_t len);
27 
28 PAGE_ALIGN DATA_SECTION PageTable bootpgtbl3 = { .entries = {
29     0x0000000000000183,
30     0x0000000000200183,
31     0x0000000000400183,
32     0x0000000000600183,
33     0x0000000000800183,
34     0x0000000000A00183,
35     0x0000000000C00183,
36     0x0000000000E00183,
37     0x0000000001000183,
38     0x0000000001200183,
39     0x0000000001400183,
40     0x0000000001600183,
41     0x0000000001800183,
42     0x0000000001A00183,
43     0x0000000001C00183,
44     0x0000000001E00183,
45     0x0000000002000183,
46 }};
47 
48 PAGE_ALIGN DATA_SECTION PageTable bootpgtbl2 = { .entries = {
49     ((uint64_t)&bootpgtbl3 - MEM_DIRECTMAP_BASE) + 0x03,
50     0
51 }};
52 
53 PAGE_ALIGN DATA_SECTION PageTable bootpgtbl1 = { .entries = {
54     ((uint64_t)&bootpgtbl2 - MEM_DIRECTMAP_BASE) + 0x03,
55     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
56     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32
57     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 48
58     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64
59     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80
60     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 96
61     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 112
62     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128
63     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144
64     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160
65     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176
66     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192
67     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208
68     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224
69     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240
70     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 256
71     [256] = ((uint64_t)&bootpgtbl2 - MEM_DIRECTMAP_BASE) + 0x03,
72 }};
73 
74 #define MAX_REGIONS 16
75 
76 static uintptr_t memRegionStart[MAX_REGIONS];
77 static uintptr_t memRegionLen[MAX_REGIONS];
78 static int memRegionIdx;
79 
80 void
MachineBoot_Entry(unsigned long magic,unsigned long addr)81 MachineBoot_Entry(unsigned long magic, unsigned long addr)
82 {
83     multiboot_info_t *mbi = (multiboot_info_t *)addr;
84 
85     Machine_EarlyInit();
86 
87     /* @r{Am I booted by a Multiboot-compliant boot loader?} */
88     if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
89     {
90       kprintf("Invalid magic number: 0x%x\n", magic);
91       //return;
92     }
93 
94     /* @r{Print out the flags.} */
95     kprintf("flags = 0x%x\n", (uint64_t) mbi->flags);
96 
97     /* @r{Are mem_* valid?} */
98     if (CHECK_FLAG (mbi->flags, 0))
99         kprintf("mem_lower = %uKB, mem_upper = %uKB\n",
100                 (unsigned) mbi->mem_lower, (unsigned) mbi->mem_upper);
101 
102     /* @r{Is boot_device valid?} */
103     if (CHECK_FLAG (mbi->flags, 1))
104         kprintf("boot_device = 0x%x\n", (unsigned) mbi->boot_device);
105 
106     /* @r{Is the command line passed?} */
107     if (CHECK_FLAG (mbi->flags, 2))
108         kprintf("cmdline = %s\n", (char *)(uintptr_t)mbi->cmdline);
109 
110     /* @r{Are mods_* valid?} */
111     if (CHECK_FLAG (mbi->flags, 3))
112     {
113         multiboot_module_t *mod;
114         int i;
115 
116         kprintf("mods_count = %d, mods_addr = 0x%x\n",
117                 (int) mbi->mods_count, (int) mbi->mods_addr);
118         for (i = 0, mod = (multiboot_module_t *)(uintptr_t)mbi->mods_addr;
119              i < mbi->mods_count;
120              i++, mod++)
121             kprintf(" mod_start = 0x%x, mod_end = 0x%x, cmdline = %s\n",
122                     (unsigned) mod->mod_start,
123                     (unsigned) mod->mod_end,
124                     (char *)(uintptr_t) mod->cmdline);
125     }
126 
127     /* @r{Bits 4 and 5 are mutually exclusive!} */
128     if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG (mbi->flags, 5))
129     {
130         kprintf("Both bits 4 and 5 are set.\n");
131         return;
132     }
133 
134     /* @r{Is the symbol table of a.out valid?} */
135     if (CHECK_FLAG (mbi->flags, 4))
136     {
137         multiboot_aout_symbol_table_t *multiboot_aout_sym = &(mbi->u.aout_sym);
138 
139         kprintf("multiboot_aout_symbol_table: tabsize = 0x%0x\n"
140                 "                             strsize = 0x%x, addr = 0x%x\n",
141                 (unsigned) multiboot_aout_sym->tabsize,
142                 (unsigned) multiboot_aout_sym->strsize,
143                 (unsigned) multiboot_aout_sym->addr);
144     }
145 
146     /* @r{Is the section header table of ELF valid?} */
147     if (CHECK_FLAG (mbi->flags, 5))
148     {
149         multiboot_elf_section_header_table_t *multiboot_elf_sec = &(mbi->u.elf_sec);
150 
151         kprintf("multiboot_elf_sec: num = %u, size = 0x%x,"
152                 " addr = 0x%x, shndx = 0x%x\n",
153                 (unsigned) multiboot_elf_sec->num, (unsigned) multiboot_elf_sec->size,
154                 (unsigned) multiboot_elf_sec->addr, (unsigned) multiboot_elf_sec->shndx);
155     }
156 
157     memRegionIdx = 0;
158 
159     /* @r{Are mmap_* valid?} */
160     if (CHECK_FLAG (mbi->flags, 6))
161     {
162 	multiboot_memory_map_t *mmap;
163 
164 	kprintf("mmap_addr = 0x%x, mmap_length = 0x%x\n",
165 		(unsigned) mbi->mmap_addr, (unsigned) mbi->mmap_length);
166 	for (mmap = (multiboot_memory_map_t *)(uintptr_t) mbi->mmap_addr;
167 	    (unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length;
168 	    mmap = (multiboot_memory_map_t *) ((unsigned long) mmap
169 				    + mmap->size + sizeof (mmap->size)))
170 	{
171 	    kprintf(" size = 0x%x, base_addr = 0x%llx,"
172 		    " length = 0x%llx, type = 0x%x\n",
173 		    (unsigned) mmap->size,
174 		    mmap->addr,
175 		    mmap->len,
176 		    (unsigned) mmap->type);
177 	    if (mmap->type == MULTIBOOT_MEMORY_AVAILABLE) {
178 		memRegionStart[memRegionIdx] = mmap->addr;
179 		memRegionLen[memRegionIdx] = mmap->len;
180 		memRegionIdx++;
181 	    }
182 	}
183     }
184 
185     // Main initialization
186     Machine_Init();
187 
188     return;
189 }
190 
191 void
MachineBoot_AddMem()192 MachineBoot_AddMem()
193 {
194     int i;
195     uintptr_t initRamEnd = 32*1024*1024;
196 
197     for (i = 0; i < memRegionIdx; i++)
198     {
199 	uintptr_t start = memRegionStart[i];
200 	uintptr_t len = memRegionLen[i];
201 
202 	if (start + len < initRamEnd)
203 	    continue;
204 
205 	if (start < initRamEnd) {
206 	    len = initRamEnd - start;
207 	    start = initRamEnd;
208 	}
209 
210 	kprintf("AddRegion: %08llx %08llx\n", start, len);
211 	PAlloc_AddRegion(start + MEM_DIRECTMAP_BASE, len);
212     }
213 }
214 
215