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