|
@@ -143,7 +143,7 @@ static void multiboot_build_memmap ( struct image *image,
|
143
|
143
|
* @v image Image
|
144
|
144
|
* @ret physaddr Physical address of command line
|
145
|
145
|
*/
|
146
|
|
-physaddr_t multiboot_add_cmdline ( struct image *image ) {
|
|
146
|
+static physaddr_t multiboot_add_cmdline ( struct image *image ) {
|
147
|
147
|
char *mb_cmdline = ( mb_cmdlines + mb_cmdline_offset );
|
148
|
148
|
size_t remaining = ( sizeof ( mb_cmdlines ) - mb_cmdline_offset );
|
149
|
149
|
char *buf = mb_cmdline;
|
|
@@ -174,28 +174,26 @@ physaddr_t multiboot_add_cmdline ( struct image *image ) {
|
174
|
174
|
}
|
175
|
175
|
|
176
|
176
|
/**
|
177
|
|
- * Build multiboot module list
|
|
177
|
+ * Add multiboot modules
|
178
|
178
|
*
|
179
|
179
|
* @v image Multiboot image
|
180
|
|
- * @v modules Module list to fill, or NULL
|
181
|
|
- * @ret count Number of modules
|
|
180
|
+ * @v start Start address for modules
|
|
181
|
+ * @v mbinfo Multiboot information structure
|
|
182
|
+ * @v modules Multiboot module list
|
|
183
|
+ * @ret rc Return status code
|
182
|
184
|
*/
|
183
|
|
-static unsigned int
|
184
|
|
-multiboot_build_module_list ( struct image *image,
|
185
|
|
- struct multiboot_module *modules,
|
186
|
|
- unsigned int limit ) {
|
|
185
|
+static int multiboot_add_modules ( struct image *image, physaddr_t start,
|
|
186
|
+ struct multiboot_info *mbinfo,
|
|
187
|
+ struct multiboot_module *modules,
|
|
188
|
+ unsigned int limit ) {
|
187
|
189
|
struct image *module_image;
|
188
|
190
|
struct multiboot_module *module;
|
189
|
|
- unsigned int count = 0;
|
190
|
|
- unsigned int insert;
|
191
|
|
- physaddr_t start;
|
192
|
|
- physaddr_t end;
|
193
|
|
- unsigned int i;
|
|
191
|
+ int rc;
|
194
|
192
|
|
195
|
193
|
/* Add each image as a multiboot module */
|
196
|
194
|
for_each_image ( module_image ) {
|
197
|
195
|
|
198
|
|
- if ( count >= limit ) {
|
|
196
|
+ if ( mbinfo->mods_count >= limit ) {
|
199
|
197
|
DBGC ( image, "MULTIBOOT %p limit of %d modules "
|
200
|
198
|
"reached\n", image, limit );
|
201
|
199
|
break;
|
|
@@ -205,37 +203,36 @@ multiboot_build_module_list ( struct image *image,
|
205
|
203
|
if ( module_image == image )
|
206
|
204
|
continue;
|
207
|
205
|
|
208
|
|
- /* At least some OSes expect the multiboot modules to
|
209
|
|
- * be in ascending order, so we have to support it.
|
210
|
|
- */
|
211
|
|
- start = user_to_phys ( module_image->data, 0 );
|
212
|
|
- end = user_to_phys ( module_image->data, module_image->len );
|
213
|
|
- for ( insert = 0 ; insert < count ; insert++ ) {
|
214
|
|
- if ( start < modules[insert].mod_start )
|
215
|
|
- break;
|
|
206
|
+ /* Page-align the module */
|
|
207
|
+ start = ( ( start + 0xfff ) & ~0xfff );
|
|
208
|
+
|
|
209
|
+ /* Prepare segment */
|
|
210
|
+ if ( ( rc = prep_segment ( phys_to_user ( start ),
|
|
211
|
+ module_image->len,
|
|
212
|
+ module_image->len ) ) != 0 ) {
|
|
213
|
+ DBGC ( image, "MULTIBOOT %p could not prepare module "
|
|
214
|
+ "%s: %s\n", image, module_image->name,
|
|
215
|
+ strerror ( rc ) );
|
|
216
|
+ return rc;
|
216
|
217
|
}
|
217
|
|
- module = &modules[insert];
|
218
|
|
- memmove ( ( module + 1 ), module,
|
219
|
|
- ( ( count - insert ) * sizeof ( *module ) ) );
|
|
218
|
+
|
|
219
|
+ /* Copy module */
|
|
220
|
+ memcpy_user ( phys_to_user ( start ), 0,
|
|
221
|
+ module_image->data, 0, module_image->len );
|
|
222
|
+
|
|
223
|
+ /* Add module to list */
|
|
224
|
+ module = &modules[mbinfo->mods_count++];
|
220
|
225
|
module->mod_start = start;
|
221
|
|
- module->mod_end = end;
|
|
226
|
+ module->mod_end = ( start + module_image->len );
|
222
|
227
|
module->string = multiboot_add_cmdline ( module_image );
|
223
|
228
|
module->reserved = 0;
|
224
|
|
-
|
225
|
|
- /* We promise to page-align modules */
|
226
|
|
- assert ( ( module->mod_start & 0xfff ) == 0 );
|
227
|
|
-
|
228
|
|
- count++;
|
229
|
|
- }
|
230
|
|
-
|
231
|
|
- /* Dump module configuration */
|
232
|
|
- for ( i = 0 ; i < count ; i++ ) {
|
233
|
|
- DBGC ( image, "MULTIBOOT %p module %d is [%x,%x)\n",
|
234
|
|
- image, i, modules[i].mod_start,
|
235
|
|
- modules[i].mod_end );
|
|
229
|
+ DBGC ( image, "MULTIBOOT %p module %s is [%x,%x)\n",
|
|
230
|
+ image, module_image->name, module->mod_start,
|
|
231
|
+ module->mod_end );
|
|
232
|
+ start += module_image->len;
|
236
|
233
|
}
|
237
|
234
|
|
238
|
|
- return count;
|
|
235
|
+ return 0;
|
239
|
236
|
}
|
240
|
237
|
|
241
|
238
|
/**
|
|
@@ -314,11 +311,12 @@ static int multiboot_find_header ( struct image *image,
|
314
|
311
|
* @v image Multiboot file
|
315
|
312
|
* @v hdr Multiboot header descriptor
|
316
|
313
|
* @ret entry Entry point
|
|
314
|
+ * @ret max Maximum used address
|
317
|
315
|
* @ret rc Return status code
|
318
|
316
|
*/
|
319
|
317
|
static int multiboot_load_raw ( struct image *image,
|
320
|
318
|
struct multiboot_header_info *hdr,
|
321
|
|
- physaddr_t *entry ) {
|
|
319
|
+ physaddr_t *entry, physaddr_t *max ) {
|
322
|
320
|
size_t offset;
|
323
|
321
|
size_t filesz;
|
324
|
322
|
size_t memsz;
|
|
@@ -349,8 +347,9 @@ static int multiboot_load_raw ( struct image *image,
|
349
|
347
|
/* Copy image to segment */
|
350
|
348
|
memcpy_user ( buffer, 0, image->data, offset, filesz );
|
351
|
349
|
|
352
|
|
- /* Record execution entry point */
|
|
350
|
+ /* Record execution entry point and maximum used address */
|
353
|
351
|
*entry = hdr->mb.entry_addr;
|
|
352
|
+ *max = ( hdr->mb.load_addr + memsz );
|
354
|
353
|
|
355
|
354
|
return 0;
|
356
|
355
|
}
|
|
@@ -360,13 +359,15 @@ static int multiboot_load_raw ( struct image *image,
|
360
|
359
|
*
|
361
|
360
|
* @v image Multiboot file
|
362
|
361
|
* @ret entry Entry point
|
|
362
|
+ * @ret max Maximum used address
|
363
|
363
|
* @ret rc Return status code
|
364
|
364
|
*/
|
365
|
|
-static int multiboot_load_elf ( struct image *image, physaddr_t *entry ) {
|
|
365
|
+static int multiboot_load_elf ( struct image *image, physaddr_t *entry,
|
|
366
|
+ physaddr_t *max ) {
|
366
|
367
|
int rc;
|
367
|
368
|
|
368
|
369
|
/* Load ELF image*/
|
369
|
|
- if ( ( rc = elf_load ( image, entry ) ) != 0 ) {
|
|
370
|
+ if ( ( rc = elf_load ( image, entry, max ) ) != 0 ) {
|
370
|
371
|
DBGC ( image, "MULTIBOOT %p ELF image failed to load: %s\n",
|
371
|
372
|
image, strerror ( rc ) );
|
372
|
373
|
return rc;
|
|
@@ -384,6 +385,7 @@ static int multiboot_load_elf ( struct image *image, physaddr_t *entry ) {
|
384
|
385
|
static int multiboot_exec ( struct image *image ) {
|
385
|
386
|
struct multiboot_header_info hdr;
|
386
|
387
|
physaddr_t entry;
|
|
388
|
+ physaddr_t max;
|
387
|
389
|
int rc;
|
388
|
390
|
|
389
|
391
|
/* Locate multiboot header, if present */
|
|
@@ -405,8 +407,8 @@ static int multiboot_exec ( struct image *image ) {
|
405
|
407
|
* the ELF header if present, and Solaris relies on this
|
406
|
408
|
* behaviour.
|
407
|
409
|
*/
|
408
|
|
- if ( ( ( rc = multiboot_load_elf ( image, &entry ) ) != 0 ) &&
|
409
|
|
- ( ( rc = multiboot_load_raw ( image, &hdr, &entry ) ) != 0 ) )
|
|
410
|
+ if ( ( ( rc = multiboot_load_elf ( image, &entry, &max ) ) != 0 ) &&
|
|
411
|
+ ( ( rc = multiboot_load_raw ( image, &hdr, &entry, &max ) ) != 0 ))
|
410
|
412
|
return rc;
|
411
|
413
|
|
412
|
414
|
/* Populate multiboot information structure */
|
|
@@ -415,11 +417,13 @@ static int multiboot_exec ( struct image *image ) {
|
415
|
417
|
MBI_FLAG_CMDLINE | MBI_FLAG_MODS );
|
416
|
418
|
mb_cmdline_offset = 0;
|
417
|
419
|
mbinfo.cmdline = multiboot_add_cmdline ( image );
|
418
|
|
- mbinfo.mods_count = multiboot_build_module_list ( image, mbmodules,
|
419
|
|
- ( sizeof(mbmodules) / sizeof(mbmodules[0]) ) );
|
420
|
420
|
mbinfo.mods_addr = virt_to_phys ( mbmodules );
|
421
|
421
|
mbinfo.mmap_addr = virt_to_phys ( mbmemmap );
|
422
|
422
|
mbinfo.boot_loader_name = virt_to_phys ( mb_bootloader_name );
|
|
423
|
+ if ( ( rc = multiboot_add_modules ( image, max, &mbinfo, mbmodules,
|
|
424
|
+ ( sizeof ( mbmodules ) /
|
|
425
|
+ sizeof ( mbmodules[0] ) ) ) ) !=0)
|
|
426
|
+ return rc;
|
423
|
427
|
|
424
|
428
|
/* Multiboot images may not return and have no callback
|
425
|
429
|
* interface, so shut everything down prior to booting the OS.
|