1 /*
2  * Linux/i386 loader
3  * Supports bzImage, zImage and Image format.
4  *
5  * Based on work by Steve Gehlbach.
6  * Portions are taken from mkelfImage.
7  *
8  * 2003-09 by SONE Takeshi
9  */
10 
11 #include "config.h"
12 #include "kernel/kernel.h"
13 #include "libopenbios/bindings.h"
14 #include "libopenbios/sys_info.h"
15 #include "context.h"
16 #include "libc/diskio.h"
17 #include "boot.h"
18 
19 #define printf printk
20 #define debug printk
21 #define strtoull_with_suffix strtol
22 
23 #define LINUX_PARAM_LOC 0x90000
24 #define COMMAND_LINE_LOC 0x91000
25 #define GDT_LOC 0x92000
26 #define STACK_LOC 0x93000
27 
28 #define E820MAX	32		/* number of entries in E820MAP */
29 struct e820entry {
30 	unsigned long long addr;	/* start of memory segment */
31 	unsigned long long size;	/* size of memory segment */
32 	unsigned long type;		/* type of memory segment */
33 #define E820_RAM	1
34 #define E820_RESERVED	2
35 #define E820_ACPI	3 /* usable as RAM once ACPI tables have been read */
36 #define E820_NVS	4
37 };
38 
39 /* The header of Linux/i386 kernel */
40 struct linux_header {
41     uint8_t  reserved1[0x1f1];		/* 0x000 */
42     uint8_t  setup_sects;		/* 0x1f1 */
43     uint16_t root_flags;		/* 0x1f2 */
44     uint8_t  reserved2[6];		/* 0x1f4 */
45     uint16_t vid_mode;			/* 0x1fa */
46     uint16_t root_dev;			/* 0x1fc */
47     uint16_t boot_sector_magic;		/* 0x1fe */
48     /* 2.00+ */
49     uint8_t  reserved3[2];		/* 0x200 */
50     uint8_t  header_magic[4];		/* 0x202 */
51     uint16_t protocol_version;		/* 0x206 */
52     uint32_t realmode_swtch;		/* 0x208 */
53     uint16_t start_sys;			/* 0x20c */
54     uint16_t kver_addr;			/* 0x20e */
55     uint8_t  type_of_loader;		/* 0x210 */
56     uint8_t  loadflags;			/* 0x211 */
57     uint16_t setup_move_size;		/* 0x212 */
58     uint32_t code32_start;		/* 0x214 */
59     uint32_t ramdisk_image;		/* 0x218 */
60     uint32_t ramdisk_size;		/* 0x21c */
61     uint8_t  reserved4[4];		/* 0x220 */
62     /* 2.01+ */
63     uint16_t heap_end_ptr;		/* 0x224 */
64     uint8_t  reserved5[2];		/* 0x226 */
65     /* 2.02+ */
66     uint32_t cmd_line_ptr;		/* 0x228 */
67     /* 2.03+ */
68     uint32_t initrd_addr_max;		/* 0x22c */
69 } __attribute__ ((packed));
70 
71 
72 /* Paramters passed to 32-bit part of Linux
73  * This is another view of the structure above.. */
74 struct linux_params {
75     uint8_t  orig_x;			/* 0x00 */
76     uint8_t  orig_y;			/* 0x01 */
77     uint16_t ext_mem_k;			/* 0x02 -- EXT_MEM_K sits here */
78     uint16_t orig_video_page;		/* 0x04 */
79     uint8_t  orig_video_mode;		/* 0x06 */
80     uint8_t  orig_video_cols;		/* 0x07 */
81     uint16_t unused2;			/* 0x08 */
82     uint16_t orig_video_ega_bx;		/* 0x0a */
83     uint16_t unused3;			/* 0x0c */
84     uint8_t  orig_video_lines;		/* 0x0e */
85     uint8_t  orig_video_isVGA;		/* 0x0f */
86     uint16_t orig_video_points;		/* 0x10 */
87 
88     /* VESA graphic mode -- linear frame buffer */
89     uint16_t lfb_width;			/* 0x12 */
90     uint16_t lfb_height;		/* 0x14 */
91     uint16_t lfb_depth;			/* 0x16 */
92     uint32_t lfb_base;			/* 0x18 */
93     uint32_t lfb_size;			/* 0x1c */
94     uint16_t cl_magic;			/* 0x20 */
95 #define CL_MAGIC_VALUE 0xA33F
96     uint16_t cl_offset;			/* 0x22 */
97     uint16_t lfb_linelength;		/* 0x24 */
98     uint8_t  red_size;			/* 0x26 */
99     uint8_t  red_pos;			/* 0x27 */
100     uint8_t  green_size;		/* 0x28 */
101     uint8_t  green_pos;			/* 0x29 */
102     uint8_t  blue_size;			/* 0x2a */
103     uint8_t  blue_pos;			/* 0x2b */
104     uint8_t  rsvd_size;			/* 0x2c */
105     uint8_t  rsvd_pos;			/* 0x2d */
106     uint16_t vesapm_seg;		/* 0x2e */
107     uint16_t vesapm_off;		/* 0x30 */
108     uint16_t pages;			/* 0x32 */
109     uint8_t  reserved4[12];		/* 0x34 -- 0x3f reserved for future expansion */
110 
111     //struct apm_bios_info apm_bios_info;	/* 0x40 */
112     uint8_t  apm_bios_info[0x40];
113     //struct drive_info_struct drive_info;	/* 0x80 */
114     uint8_t  drive_info[0x20];
115     //struct sys_desc_table sys_desc_table;	/* 0xa0 */
116     uint8_t  sys_desc_table[0x140];
117     uint32_t alt_mem_k;			/* 0x1e0 */
118     uint8_t  reserved5[4];		/* 0x1e4 */
119     uint8_t  e820_map_nr;		/* 0x1e8 */
120     uint8_t  reserved6[9];		/* 0x1e9 */
121     uint16_t mount_root_rdonly;		/* 0x1f2 */
122     uint8_t  reserved7[4];		/* 0x1f4 */
123     uint16_t ramdisk_flags;		/* 0x1f8 */
124 #define RAMDISK_IMAGE_START_MASK  	0x07FF
125 #define RAMDISK_PROMPT_FLAG		0x8000
126 #define RAMDISK_LOAD_FLAG		0x4000
127     uint8_t  reserved8[2];		/* 0x1fa */
128     uint16_t orig_root_dev;		/* 0x1fc */
129     uint8_t  reserved9[1];		/* 0x1fe */
130     uint8_t  aux_device_info;		/* 0x1ff */
131     uint8_t  reserved10[2];		/* 0x200 */
132     uint8_t  param_block_signature[4];	/* 0x202 */
133     uint16_t param_block_version;	/* 0x206 */
134     uint8_t  reserved11[8];		/* 0x208 */
135     uint8_t  loader_type;		/* 0x210 */
136 #define LOADER_TYPE_LOADLIN         1
137 #define LOADER_TYPE_BOOTSECT_LOADER 2
138 #define LOADER_TYPE_SYSLINUX        3
139 #define LOADER_TYPE_ETHERBOOT       4
140 #define LOADER_TYPE_KERNEL          5
141     uint8_t  loader_flags;		/* 0x211 */
142     uint8_t  reserved12[2];		/* 0x212 */
143     uint32_t kernel_start;		/* 0x214 */
144     uint32_t initrd_start;		/* 0x218 */
145     uint32_t initrd_size;		/* 0x21c */
146     uint8_t  reserved12_5[8];		/* 0x220 */
147     uint32_t cmd_line_ptr;		/* 0x228 */
148     uint8_t  reserved13[164];		/* 0x22c */
149     struct e820entry e820_map[E820MAX];	/* 0x2d0 */
150     uint8_t  reserved16[688];		/* 0x550 */
151 #define COMMAND_LINE_SIZE 256
152     /* Command line is copied here by 32-bit i386/kernel/head.S.
153      * So I will follow the boot protocol, rather than putting it
154      * directly here. --ts1 */
155     uint8_t  command_line[COMMAND_LINE_SIZE]; /* 0x800 */
156     uint8_t  reserved17[1792];		/* 0x900 - 0x1000 */
157 };
158 
159 static uint64_t forced_memsize;
160 static int fd;
161 
file_size(void)162 static unsigned long file_size(void)
163 {
164 	long long fpos, fsize;
165 
166 	/* Save current position */
167 	fpos = tell(fd);
168 
169 	/* Go to end of file and get position */
170 	seek_io(fd, -1);
171 	fsize = tell(fd);
172 
173 	/* Go back to old position */
174 	seek_io(fd, 0);
175 	seek_io(fd, fpos);
176 
177 	return fsize;
178 }
179 
180 /* Load the first part the file and check if it's Linux */
load_linux_header(struct linux_header * hdr)181 static uint32_t load_linux_header(struct linux_header *hdr)
182 {
183     int load_high;
184     uint32_t kern_addr;
185 
186     if (read_io(fd, hdr, sizeof *hdr) != sizeof *hdr) {
187 	debug("Can't read Linux header\n");
188 	return 0;
189     }
190     if (hdr->boot_sector_magic != 0xaa55) {
191 	debug("Not a Linux kernel image\n");
192 	return 0;
193     }
194 
195     /* Linux is found. Print some information */
196     if (memcmp(hdr->header_magic, "HdrS", 4) != 0) {
197 	/* This may be floppy disk image or something.
198 	 * Perform a simple (incomplete) sanity check. */
199 	if (hdr->setup_sects >= 16
200 		|| file_size() - (hdr->setup_sects<<9) >= 512<<10) {
201 	    debug("This looks like a bootdisk image but not like Linux...\n");
202 	    return 0;
203 	}
204 
205 	printf("Possible very old Linux");
206 	/* This kernel does not even have a protocol version.
207 	 * Force the value. */
208 	hdr->protocol_version = 0; /* pre-2.00 */
209     } else
210 	printf("Found Linux");
211     if (hdr->protocol_version >= 0x200 && hdr->kver_addr) {
212 	char kver[256];
213 	seek_io(fd, hdr->kver_addr + 0x200);
214 	if (read_io(fd, kver, sizeof kver) != 0) {
215 	    kver[255] = 0;
216 	    printf(" version %s", kver);
217 	}
218     }
219     debug(" (protocol %#x)", hdr->protocol_version);
220     load_high = 0;
221     if (hdr->protocol_version >= 0x200) {
222 	debug(" (loadflags %#x)", hdr->loadflags);
223 	load_high = hdr->loadflags & 1;
224     }
225     if (load_high) {
226 	printf(" bzImage");
227 	kern_addr = 0x100000;
228     } else {
229 	printf(" zImage or Image");
230 	kern_addr = 0x1000;
231     }
232     printf(".\n");
233 
234     return kern_addr;
235 }
236 
237 /* Set up parameters for 32-bit kernel */
238 static void
init_linux_params(struct linux_params * params,struct linux_header * hdr)239 init_linux_params(struct linux_params *params, struct linux_header *hdr)
240 {
241     debug("Setting up parameters at %#lx\n", virt_to_phys(params));
242     memset(params, 0, sizeof *params);
243 
244     /* Copy some useful values from header */
245     params->mount_root_rdonly = hdr->root_flags;
246     params->orig_root_dev = hdr->root_dev;
247 
248     /* Video parameters.
249      * This assumes we have VGA in standard 80x25 text mode,
250      * just like our vga.c does.
251      * Cursor position is filled later to allow some more printf's. */
252     params->orig_video_mode = 3;
253     params->orig_video_cols = 80;
254     params->orig_video_lines = 25;
255     params->orig_video_isVGA = 1;
256     params->orig_video_points = 16;
257 
258     params->loader_type = 0xff; /* Unregistered Linux loader */
259 }
260 
261 /* Memory map */
262 static void
set_memory_size(struct linux_params * params,struct sys_info * info)263 set_memory_size(struct linux_params *params, struct sys_info *info)
264 {
265     int i;
266     uint64_t end;
267     uint32_t ramtop = 0;
268     struct e820entry *linux_map;
269     struct memrange *filo_map;
270 
271     linux_map = params->e820_map;
272     filo_map = info->memrange;
273     for (i = 0; i < info->n_memranges; i++, linux_map++, filo_map++) {
274 	if (i < E820MAX) {
275 	    /* Convert to BIOS e820 style */
276 	    linux_map->addr = filo_map->base;
277 	    linux_map->size = filo_map->size;
278 	    linux_map->type = E820_RAM;
279 	    debug("%016Lx - %016Lx\n", linux_map->addr,
280 		    linux_map->addr + linux_map->size);
281 	    params->e820_map_nr = i+1;
282 	}
283 
284 	/* Find out top of RAM. XXX This ignores hole above 1MB */
285 	end = filo_map->base + filo_map->size;
286 	if (end < (1ULL << 32)) { /* don't count memory above 4GB */
287 	    if (end > ramtop)
288 		ramtop = (uint32_t) end;
289 	}
290     }
291     debug("ramtop=%#x\n", ramtop);
292     /* Size of memory above 1MB in KB */
293     params->alt_mem_k = (ramtop - (1<<20)) >> 10;
294     /* old style, 64MB max */
295     if (ramtop >= (64<<20))
296 	params->ext_mem_k = (63<<10);
297     else
298 	params->ext_mem_k = params->alt_mem_k;
299     debug("ext_mem_k=%d, alt_mem_k=%d\n", params->ext_mem_k, params->alt_mem_k);
300 }
301 
302 /*
303  * Parse command line
304  * Some parameters, like initrd=<file>, are not passed to kernel,
305  * we are responsible to process them.
306  * Parameters for kernel are copied to kern_cmdline. Returns name of initrd.
307  */
parse_command_line(const char * orig_cmdline,char * kern_cmdline)308 static char *parse_command_line(const char *orig_cmdline, char *kern_cmdline)
309 {
310     const char *start, *sep, *end, *val;
311     char name[64];
312     unsigned long len;
313     int k_len;
314     int to_kern;
315     char *initrd = NULL;
316     int toolong = 0;
317 
318     forced_memsize = 0;
319 
320     if (!orig_cmdline) {
321         *kern_cmdline = '\0';
322         return NULL;
323     }
324 
325     k_len = 0;
326     debug("original command line: \"%s\"\n", orig_cmdline);
327     debug("kernel command line at %#lx\n", virt_to_phys(kern_cmdline));
328 
329     start = orig_cmdline;
330     while (*start == ' ')
331 	start++;
332     while (*start) {
333 	end = strchr(start, ' ');
334 	if (!end)
335 	    end = start + strlen(start);
336 	sep = strchr(start, '=');
337 	if (!sep || sep > end)
338 	    sep = end;
339 	len = sep - start;
340 	if (len >= sizeof(name))
341 	    len = sizeof(name) - 1;
342 	memcpy(name, start, len);
343 	name[len] = 0;
344 
345 	if (*sep == '=') {
346 	    val = sep + 1;
347 	    len = end - val;
348 	} else {
349             val = NULL;
350 	    len = 0;
351 	}
352 
353 	/* Only initrd= and mem= are handled here. vga= is not,
354 	 * which I believe is a paramter to the realmode part of Linux,
355 	 * which we don't execute. */
356 	if (strcmp(name, "initrd") == 0) {
357 	    if (!val)
358 		printf("Missing filename to initrd parameter\n");
359 	    else {
360 		initrd = malloc(len + 1);
361 		memcpy(initrd, val, len);
362 		initrd[len] = 0;
363 		debug("initrd=%s\n", initrd);
364 	    }
365 	    /* Don't pass this to kernel */
366 	    to_kern = 0;
367 	} else if (strcmp(name, "mem") == 0) {
368 	    if (!val)
369 		printf("Missing value for mem parameter\n");
370 	    else {
371 		forced_memsize = strtoull_with_suffix(val, (char**)&val, 0);
372 		if (forced_memsize == 0)
373 		    printf("Invalid mem option, ignored\n");
374 		if (val != end) {
375 		    printf("Garbage after mem=<size>, ignored\n");
376 		    forced_memsize = 0;
377 		}
378 		debug("mem=%llu\n", (unsigned long long)forced_memsize);
379 	    }
380 	    /* mem= is for both loader and kernel */
381 	    to_kern = 1;
382 	} else
383 	    to_kern = 1;
384 
385 	if (to_kern) {
386 	    /* Copy to kernel command line buffer */
387 	    if (k_len != 0)
388 		kern_cmdline[k_len++] = ' '; /* put separator */
389 	    len = end - start;
390 	    if (k_len + len >= COMMAND_LINE_SIZE) {
391 		len = COMMAND_LINE_SIZE - k_len - 1;
392 		if (!toolong) {
393 		    printf("Kernel command line is too long; truncated to "
394 			    "%d bytes\n", COMMAND_LINE_SIZE-1);
395 		    toolong = 1;
396 		}
397 	    }
398 	    memcpy(kern_cmdline + k_len, start, len);
399 	    k_len += len;
400 	}
401 
402 	start = end;
403 	while (*start == ' ')
404 	    start++;
405     }
406     kern_cmdline[k_len] = 0;
407     debug("kernel command line (%d bytes): \"%s\"\n", k_len, kern_cmdline);
408 
409     return initrd;
410 }
411 
412 /* Set command line location */
set_command_line_loc(struct linux_params * params,struct linux_header * hdr)413 static void set_command_line_loc(struct linux_params *params,
414 	struct linux_header *hdr)
415 {
416     if (hdr->protocol_version >= 0x202) {
417 	/* new style */
418 	params->cmd_line_ptr = COMMAND_LINE_LOC;
419     } else {
420 	/* old style */
421 	params->cl_magic = CL_MAGIC_VALUE;
422 	params->cl_offset = COMMAND_LINE_LOC - LINUX_PARAM_LOC;
423     }
424 }
425 
426 /* Load 32-bit part of kernel */
load_linux_kernel(struct linux_header * hdr,uint32_t kern_addr)427 static int load_linux_kernel(struct linux_header *hdr, uint32_t kern_addr)
428 {
429     uint32_t kern_offset, kern_size;
430 
431     if (hdr->setup_sects == 0)
432 	hdr->setup_sects = 4;
433     kern_offset = (hdr->setup_sects + 1) * 512;
434     seek_io(fd, kern_offset);
435     kern_size = file_size() - kern_offset;
436     debug("offset=%#x addr=%#x size=%#x\n", kern_offset, kern_addr, kern_size);
437 
438 #if 0
439     if (using_devsize) {
440 	printf("Attempt to load up to end of device as kernel; "
441 		"specify the image size\n");
442 	return 0;
443     }
444 #endif
445 
446     printf("Loading kernel... ");
447     if ((uint32_t)read_io(fd, phys_to_virt(kern_addr), kern_size) != kern_size) {
448 	printf("Can't read kernel\n");
449 	return 0;
450     }
451     printf("ok\n");
452 
453     return kern_size;
454 }
455 
load_initrd(struct linux_header * hdr,uint32_t kern_end,struct linux_params * params,const char * initrd_file)456 static int load_initrd(struct linux_header *hdr, uint32_t kern_end,
457                        struct linux_params *params, const char *initrd_file)
458 {
459     uint32_t max;
460     uint32_t start, end, size;
461     uint64_t forced;
462 
463     fd = open_io(initrd_file);
464     if (fd == -1) {
465 	printf("Can't open initrd: %s\n", initrd_file);
466 	return -1;
467     }
468 
469 #if 0
470     if (using_devsize) {
471 	printf("Attempt to load up to end of device as initrd; "
472 		"specify the image size\n");
473 	return -1;
474     }
475 #endif
476 
477     size = file_size();
478 
479 
480     /* Find out the kernel's restriction on how high the initrd can be
481      * placed */
482     if (hdr->protocol_version >= 0x203)
483 	max = hdr->initrd_addr_max;
484     else
485 	max = 0x38000000; /* Hardcoded value for older kernels */
486 
487     /* FILO itself is at the top of RAM. (relocated)
488      * So, try putting initrd just below us. */
489     end = virt_to_phys(_start);
490     if (end > max)
491 	end = max;
492 
493     /* If "mem=" option is given, we have to put the initrd within
494      * the specified range. */
495     if (forced_memsize) {
496 	forced = forced_memsize;
497 	if (forced > max)
498 	    forced = max;
499 	/* If the "mem=" is lower, it's easy */
500 	if (forced <= end)
501 	    end = forced;
502 	else {
503 	    /* Otherwise, see if we can put it above us */
504 	    if (virt_to_phys(_end) + size <= forced)
505 		end = forced; /* Ok */
506 	}
507     }
508 
509     start = end - size;
510     start &= ~0xfff; /* page align */
511     end = start + size;
512 
513     debug("start=%#x end=%#x\n", start, end);
514 
515     if (start < kern_end) {
516 	printf("Initrd is too big to fit in memory\n");
517 	return -1;
518     }
519 
520     printf("Loading initrd... ");
521     if ((uint32_t)read_io(fd, phys_to_virt(start), size) != size) {
522 	printf("Can't read initrd\n");
523 	return -1;
524     }
525     printf("ok\n");
526 
527     params->initrd_start = start;
528     params->initrd_size = size;
529 
530     close_io(fd);
531 
532     return 0;
533 }
534 
hardware_setup(void)535 static void hardware_setup(void)
536 {
537     /* Disable nmi */
538     outb(0x80, 0x70);
539 
540     /* Make sure any coprocessor is properly reset.. */
541     outb(0, 0xf0);
542     outb(0, 0xf1);
543 
544     /* we're getting screwed again and again by this problem of the 8259.
545      * so we're going to leave this lying around for inclusion into
546      * crt0.S on an as-needed basis.
547      *
548      * well, that went ok, I hope. Now we have to reprogram the interrupts :-(
549      * we put them right after the intel-reserved hardware interrupts, at
550      * int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
551      * messed this up with the original PC, and they haven't been able to
552      * rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
553      * which is used for the internal hardware interrupts as well. We just
554      * have to reprogram the 8259's, and it isn't fun.
555      */
556 
557     outb(0x11, 0x20);		/* initialization sequence to 8259A-1 */
558     outb(0x11, 0xA0);		/* and to 8259A-2 */
559 
560     outb(0x20, 0x21);		/* start of hardware int's (0x20) */
561     outb(0x28, 0xA1);		/* start of hardware int's 2 (0x28) */
562 
563     outb(0x04, 0x21);		/* 8259-1 is master */
564     outb(0x02, 0xA1);		/* 8259-2 is slave */
565 
566     outb(0x01, 0x21);		/* 8086 mode for both */
567     outb(0x01, 0xA1);
568 
569     outb(0xFF, 0xA1);		/* mask off all interrupts for now */
570     outb(0xFB, 0x21);		/* mask all irq's but irq2 which is cascaded */
571 }
572 
573 /* Start Linux */
start_linux(uint32_t kern_addr)574 static int start_linux(uint32_t kern_addr)
575 {
576     struct context *ctx;
577     //extern int cursor_x, cursor_y;
578 
579     ctx = init_context(phys_to_virt(STACK_LOC), 4096, 0);
580 
581     /* Entry point */
582     ctx->pc = kern_addr;
583     ctx->npc = kern_addr + 4;
584 
585     debug("pc=%#x\n", kern_addr);
586     printf("Jumping to entry point...\n");
587 
588 #ifdef VGA_CONSOLE
589     /* Update VGA cursor position.
590      * This must be here because the printf changes the value! */
591     params->orig_x = cursor_x;
592     params->orig_y = cursor_y;
593 #endif
594 
595     /* Go... */
596     ctx = switch_to(ctx);
597 
598     /* It's impossible but... */
599     printf("Returned with o0=%#llx\n", ctx->regs[REG_O0]);
600 
601     return ctx->regs[REG_O0];
602 }
603 
linux_load(struct sys_info * info,const char * file,const char * cmdline)604 int linux_load(struct sys_info *info, const char *file, const char *cmdline)
605 {
606     struct linux_header hdr;
607     struct linux_params *params;
608     uint32_t kern_addr, kern_size;
609     char *initrd_file = NULL;
610 
611     fd = open_io(file);
612     if (fd == -1)
613 	return -1;
614 
615     kern_addr = load_linux_header(&hdr);
616     if (kern_addr == 0) {
617 	close_io(fd);
618 	return LOADER_NOT_SUPPORT;
619     }
620 
621     debug("[sparc64] Booting kernel '%s' ", file);
622     if (cmdline)
623         debug("with parameters '%s'\n", cmdline);
624     else
625         debug("without parameters.\n");
626 
627     params = phys_to_virt(LINUX_PARAM_LOC);
628     init_linux_params(params, &hdr);
629     set_memory_size(params, info);
630     initrd_file = parse_command_line(cmdline, phys_to_virt(COMMAND_LINE_LOC));
631     set_command_line_loc(params, &hdr);
632 
633     kern_size = load_linux_kernel(&hdr, kern_addr);
634     if (kern_size == 0) {
635 	if (initrd_file)
636 	    free(initrd_file);
637 	return -1;
638     }
639 
640     if (initrd_file) {
641 	if (load_initrd(&hdr, kern_addr+kern_size, params, initrd_file)
642 		!= 0) {
643 	    free(initrd_file);
644 	    return -1;
645 	}
646 	free(initrd_file);
647     }
648 
649     hardware_setup();
650 
651     start_linux(kern_addr);
652     return 0;
653 }
654