|
@@ -1,208 +0,0 @@
|
1
|
|
-/* Multiboot support
|
2
|
|
- *
|
3
|
|
- * 2003-07-02 mmap fix and header probe by SONE Takeshi
|
4
|
|
- */
|
5
|
|
-
|
6
|
|
-struct multiboot_mods {
|
7
|
|
- unsigned mod_start;
|
8
|
|
- unsigned mod_end;
|
9
|
|
- unsigned char *string;
|
10
|
|
- unsigned reserved;
|
11
|
|
-};
|
12
|
|
-
|
13
|
|
-struct multiboot_mmap {
|
14
|
|
- unsigned int size;
|
15
|
|
- unsigned int base_addr_low;
|
16
|
|
- unsigned int base_addr_high;
|
17
|
|
- unsigned int length_low;
|
18
|
|
- unsigned int length_high;
|
19
|
|
- unsigned int type;
|
20
|
|
-};
|
21
|
|
-
|
22
|
|
-/* The structure of a Multiboot 0.6 parameter block. */
|
23
|
|
-struct multiboot_info {
|
24
|
|
- unsigned int flags;
|
25
|
|
-#define MULTIBOOT_MEM_VALID 0x01
|
26
|
|
-#define MULTIBOOT_BOOT_DEV_VALID 0x02
|
27
|
|
-#define MULTIBOOT_CMDLINE_VALID 0x04
|
28
|
|
-#define MULTIBOOT_MODS_VALID 0x08
|
29
|
|
-#define MULTIBOOT_AOUT_SYMS_VALID 0x10
|
30
|
|
-#define MULTIBOOT_ELF_SYMS_VALID 0x20
|
31
|
|
-#define MULTIBOOT_MMAP_VALID 0x40
|
32
|
|
- unsigned int memlower;
|
33
|
|
- unsigned int memupper;
|
34
|
|
- unsigned int bootdev;
|
35
|
|
- unsigned int cmdline; /* physical address of the command line */
|
36
|
|
- unsigned mods_count;
|
37
|
|
- struct multiboot_mods *mods_addr;
|
38
|
|
- unsigned syms_num;
|
39
|
|
- unsigned syms_size;
|
40
|
|
- unsigned syms_addr;
|
41
|
|
- unsigned syms_shndx;
|
42
|
|
- unsigned mmap_length;
|
43
|
|
- unsigned mmap_addr;
|
44
|
|
- /* The structure actually ends here, so I might as well put
|
45
|
|
- * the ugly e820 parameters here...
|
46
|
|
- */
|
47
|
|
- struct multiboot_mmap mmap[E820MAX];
|
48
|
|
-};
|
49
|
|
-
|
50
|
|
-/* Multiboot image header (minimal part) */
|
51
|
|
-struct multiboot_header {
|
52
|
|
- unsigned int magic;
|
53
|
|
-#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
|
54
|
|
- unsigned int flags;
|
55
|
|
- unsigned int checksum;
|
56
|
|
-};
|
57
|
|
-
|
58
|
|
-static struct multiboot_header *mbheader;
|
59
|
|
-static unsigned int mbimgoffset, mboffset;
|
60
|
|
-static unsigned char mbbuffer[12];
|
61
|
|
-
|
62
|
|
-static struct multiboot_info mbinfo;
|
63
|
|
-
|
64
|
|
-static void multiboot_init(void)
|
65
|
|
-{
|
66
|
|
- mbheader = NULL;
|
67
|
|
- mbimgoffset = 0;
|
68
|
|
- mboffset = 0;
|
69
|
|
-}
|
70
|
|
-
|
71
|
|
-/* Remember this probing function is actually different from the usual probing
|
72
|
|
- * functions, since the Multiboot header is somewhere in the first 8KB of the
|
73
|
|
- * image and it is byte aligned, but there is not much more known about how to
|
74
|
|
- * find it. In the Etherboot context the most complicated issue is that the
|
75
|
|
- * image has to be processed block-by-block, with unknown block size and no
|
76
|
|
- * guarantees about block alignment with respect to the image. */
|
77
|
|
-static void multiboot_peek(unsigned char *data, int len)
|
78
|
|
-{
|
79
|
|
- struct multiboot_header *h;
|
80
|
|
-
|
81
|
|
- /* If we have already searched the first 8KB of the image or if we have
|
82
|
|
- * already found a valid Multiboot header, skip this code. */
|
83
|
|
- if ((mboffset == 12) || (mbimgoffset >= 8192))
|
84
|
|
- return;
|
85
|
|
-
|
86
|
|
- if (mbimgoffset + len >= 8192)
|
87
|
|
- len = 8192 - mbimgoffset;
|
88
|
|
-
|
89
|
|
- /* This piece of code is pretty stupid, since it always copies data, even
|
90
|
|
- * if it is word aligned. This shouldn't matter too much on platforms that
|
91
|
|
- * use the Multiboot spec, since the processors are usually reasonably fast
|
92
|
|
- * and this code is only executed for the first 8KB of the image. Feel
|
93
|
|
- * free to improve it, but be prepared to write quite a lot of code that
|
94
|
|
- * deals with non-aligned data with respect to the image to load. */
|
95
|
|
- while (len > 0) {
|
96
|
|
- mbimgoffset++;
|
97
|
|
- memcpy(mbbuffer + mboffset, data, 1);
|
98
|
|
- mboffset++;
|
99
|
|
- data++;
|
100
|
|
- len--;
|
101
|
|
- if (mboffset == 4) {
|
102
|
|
- /* Accumulated a word into the buffer. */
|
103
|
|
- h = (struct multiboot_header *)mbbuffer;
|
104
|
|
- if (h->magic != MULTIBOOT_HEADER_MAGIC) {
|
105
|
|
- /* Wrong magic, this cannot be the start of the header. */
|
106
|
|
- mboffset = 0;
|
107
|
|
- }
|
108
|
|
- } else if (mboffset == 12) {
|
109
|
|
- /* Accumulated the minimum header data into the buffer. */
|
110
|
|
- h = (struct multiboot_header *)mbbuffer;
|
111
|
|
- if (h->magic + h->flags + h->checksum != 0) {
|
112
|
|
- /* Checksum error, not a valid header. Check for a possible
|
113
|
|
- * header starting in the current flag/checksum field. */
|
114
|
|
- if (h->flags == MULTIBOOT_HEADER_MAGIC) {
|
115
|
|
- mboffset -= 4;
|
116
|
|
- memmove(mbbuffer, mbbuffer + 4, mboffset);
|
117
|
|
- } else if (h->checksum == MULTIBOOT_HEADER_MAGIC) {
|
118
|
|
- mboffset -= 8;
|
119
|
|
- memmove(mbbuffer, mbbuffer + 8, mboffset);
|
120
|
|
- } else {
|
121
|
|
- mboffset = 0;
|
122
|
|
- }
|
123
|
|
- } else {
|
124
|
|
- printf("Multiboot... ");
|
125
|
|
- mbheader = h;
|
126
|
|
- if ((h->flags & 0xfffc) != 0) {
|
127
|
|
- printf("\nERROR: Unsupported Multiboot requirements flags\n");
|
128
|
|
- longjmp(restart_etherboot, -2);
|
129
|
|
- }
|
130
|
|
- break;
|
131
|
|
- }
|
132
|
|
- }
|
133
|
|
- }
|
134
|
|
- mbimgoffset += len;
|
135
|
|
-}
|
136
|
|
-
|
137
|
|
-static inline void multiboot_boot(unsigned long entry)
|
138
|
|
-{
|
139
|
|
- unsigned char cmdline[512], *c;
|
140
|
|
- int i;
|
141
|
|
- if (!mbheader)
|
142
|
|
- return;
|
143
|
|
- /* Etherboot limits the command line to the kernel name,
|
144
|
|
- * default parameters and user prompted parameters. All of
|
145
|
|
- * them are shorter than 256 bytes. As the kernel name and
|
146
|
|
- * the default parameters come from the same BOOTP/DHCP entry
|
147
|
|
- * (or if they don't, the parameters are empty), only two
|
148
|
|
- * strings of the maximum size are possible. Note this buffer
|
149
|
|
- * can overrun if a stupid file name is chosen. Oh well. */
|
150
|
|
- c = cmdline;
|
151
|
|
- for (i = 0; KERNEL_BUF[i] != '\0'; i++) {
|
152
|
|
- switch (KERNEL_BUF[i]) {
|
153
|
|
- case ' ':
|
154
|
|
- case '\\':
|
155
|
|
- case '"':
|
156
|
|
- *c++ = '\\';
|
157
|
|
- break;
|
158
|
|
- default:
|
159
|
|
- break;
|
160
|
|
- }
|
161
|
|
- *c++ = KERNEL_BUF[i];
|
162
|
|
- }
|
163
|
|
- if (addparam != NULL) {
|
164
|
|
- *c++ = ' ';
|
165
|
|
- memcpy(c, addparam, addparamlen);
|
166
|
|
- c += addparamlen;
|
167
|
|
- }
|
168
|
|
- (void)sprintf(c, " -retaddr %#lX", virt_to_phys(xend32));
|
169
|
|
-
|
170
|
|
- mbinfo.flags = MULTIBOOT_MMAP_VALID | MULTIBOOT_MEM_VALID |MULTIBOOT_CMDLINE_VALID;
|
171
|
|
- mbinfo.memlower = meminfo.basememsize;
|
172
|
|
- mbinfo.memupper = meminfo.memsize;
|
173
|
|
- mbinfo.bootdev = 0; /* not booted from disk */
|
174
|
|
- mbinfo.cmdline = virt_to_phys(cmdline);
|
175
|
|
- for (i = 0; i < (int) meminfo.map_count; i++) {
|
176
|
|
- mbinfo.mmap[i].size = sizeof(struct multiboot_mmap)
|
177
|
|
- - sizeof(unsigned int);
|
178
|
|
- mbinfo.mmap[i].base_addr_low =
|
179
|
|
- (unsigned int) meminfo.map[i].addr;
|
180
|
|
- mbinfo.mmap[i].base_addr_high =
|
181
|
|
- (unsigned int) (meminfo.map[i].addr >> 32);
|
182
|
|
- mbinfo.mmap[i].length_low =
|
183
|
|
- (unsigned int) meminfo.map[i].size;
|
184
|
|
- mbinfo.mmap[i].length_high =
|
185
|
|
- (unsigned int) (meminfo.map[i].size >> 32);
|
186
|
|
- mbinfo.mmap[i].type = meminfo.map[i].type;
|
187
|
|
- }
|
188
|
|
- mbinfo.mmap_length = meminfo.map_count * sizeof(struct multiboot_mmap);
|
189
|
|
- mbinfo.mmap_addr = virt_to_phys(mbinfo.mmap);
|
190
|
|
-
|
191
|
|
- /* The Multiboot 0.6 spec requires all segment registers to be
|
192
|
|
- * loaded with an unrestricted, writeable segment.
|
193
|
|
- * xstart32 does this for us.
|
194
|
|
- */
|
195
|
|
-
|
196
|
|
- /* Start the kernel, passing the Multiboot information record
|
197
|
|
- * and the magic number. */
|
198
|
|
- os_regs.eax = 0x2BADB002;
|
199
|
|
- os_regs.ebx = virt_to_phys(&mbinfo);
|
200
|
|
- xstart32(entry);
|
201
|
|
- /* A Multiboot kernel by default never returns - there is nothing in the
|
202
|
|
- * specification about what happens to the boot loader after the kernel has
|
203
|
|
- * been started. Thus if the kernel returns it is definitely aware of the
|
204
|
|
- * semantics involved (i.e. the "-retaddr" parameter). Do not treat this
|
205
|
|
- * as an error, but restart with a fresh DHCP request in order to activate
|
206
|
|
- * the menu again in case one is used. */
|
207
|
|
- longjmp(restart_etherboot, 2);
|
208
|
|
-}
|