|
|
1.1 ! root 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: ! 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 */ ! 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 ! 239: init_linux_params(struct linux_params *params, struct linux_header *hdr) ! 240: { ! 241: debug("Setting up paramters 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 ! 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: */ ! 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=%Lu\n", 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 */ ! 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 */ ! 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: ! 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: ! 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 */ ! 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=%#x\n", ctx->regs[REG_O0]); ! 600: ! 601: return ctx->regs[REG_O0]; ! 602: } ! 603: ! 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: ! 616: kern_addr = load_linux_header(&hdr); ! 617: if (kern_addr == 0) { ! 618: close_io(fd); ! 619: return LOADER_NOT_SUPPORT; ! 620: } ! 621: ! 622: params = phys_to_virt(LINUX_PARAM_LOC); ! 623: init_linux_params(params, &hdr); ! 624: set_memory_size(params, info); ! 625: initrd_file = parse_command_line(cmdline, phys_to_virt(COMMAND_LINE_LOC)); ! 626: set_command_line_loc(params, &hdr); ! 627: ! 628: kern_size = load_linux_kernel(&hdr, kern_addr); ! 629: if (kern_size == 0) { ! 630: if (initrd_file) ! 631: free(initrd_file); ! 632: return -1; ! 633: } ! 634: ! 635: if (initrd_file) { ! 636: if (load_initrd(&hdr, kern_addr+kern_size, params, initrd_file) ! 637: != 0) { ! 638: free(initrd_file); ! 639: return -1; ! 640: } ! 641: free(initrd_file); ! 642: } ! 643: ! 644: hardware_setup(); ! 645: ! 646: start_linux(kern_addr); ! 647: return 0; ! 648: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.