|
|
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 "segment.h" ! 17: #include "loadfs.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: uint64_t forced_memsize; ! 160: ! 161: /* Load the first part the file and check if it's Linux */ ! 162: static uint32_t load_linux_header(struct linux_header *hdr) ! 163: { ! 164: int load_high; ! 165: uint32_t kern_addr; ! 166: ! 167: if (lfile_read(hdr, sizeof *hdr) != sizeof *hdr) { ! 168: debug("Can't read Linux header\n"); ! 169: return 0; ! 170: } ! 171: if (hdr->boot_sector_magic != 0xaa55) { ! 172: debug("Not a Linux kernel image\n"); ! 173: return 0; ! 174: } ! 175: ! 176: /* Linux is found. Print some information */ ! 177: if (memcmp(hdr->header_magic, "HdrS", 4) != 0) { ! 178: /* This may be floppy disk image or something. ! 179: * Perform a simple (incomplete) sanity check. */ ! 180: if (hdr->setup_sects >= 16 ! 181: || file_size() - (hdr->setup_sects<<9) >= 512<<10) { ! 182: debug("This looks like a bootdisk image but not like Linux...\n"); ! 183: return 0; ! 184: } ! 185: ! 186: printf("Possible very old Linux"); ! 187: /* This kernel does not even have a protocol version. ! 188: * Force the value. */ ! 189: hdr->protocol_version = 0; /* pre-2.00 */ ! 190: } else ! 191: printf("Found Linux"); ! 192: if (hdr->protocol_version >= 0x200 && hdr->kver_addr) { ! 193: char kver[256]; ! 194: file_seek(hdr->kver_addr + 0x200); ! 195: if (lfile_read(kver, sizeof kver) != 0) { ! 196: kver[255] = 0; ! 197: printf(" version %s", kver); ! 198: } ! 199: } ! 200: debug(" (protocol %#x)", hdr->protocol_version); ! 201: load_high = 0; ! 202: if (hdr->protocol_version >= 0x200) { ! 203: debug(" (loadflags %#x)", hdr->loadflags); ! 204: load_high = hdr->loadflags & 1; ! 205: } ! 206: if (load_high) { ! 207: printf(" bzImage"); ! 208: kern_addr = 0x100000; ! 209: } else { ! 210: printf(" zImage or Image"); ! 211: kern_addr = 0x1000; ! 212: } ! 213: printf(".\n"); ! 214: ! 215: return kern_addr; ! 216: } ! 217: ! 218: /* Set up parameters for 32-bit kernel */ ! 219: static void ! 220: init_linux_params(struct linux_params *params, struct linux_header *hdr) ! 221: { ! 222: debug("Setting up paramters at %#lx\n", virt_to_phys(params)); ! 223: memset(params, 0, sizeof *params); ! 224: ! 225: /* Copy some useful values from header */ ! 226: params->mount_root_rdonly = hdr->root_flags; ! 227: params->orig_root_dev = hdr->root_dev; ! 228: ! 229: /* Video parameters. ! 230: * This assumes we have VGA in standard 80x25 text mode, ! 231: * just like our vga.c does. ! 232: * Cursor position is filled later to allow some more printf's. */ ! 233: params->orig_video_mode = 3; ! 234: params->orig_video_cols = 80; ! 235: params->orig_video_lines = 25; ! 236: params->orig_video_isVGA = 1; ! 237: params->orig_video_points = 16; ! 238: ! 239: params->loader_type = 0xff; /* Unregistered Linux loader */ ! 240: } ! 241: ! 242: /* Memory map */ ! 243: static void ! 244: set_memory_size(struct linux_params *params, struct sys_info *info) ! 245: { ! 246: int i; ! 247: uint64_t end; ! 248: uint32_t ramtop = 0; ! 249: struct e820entry *linux_map; ! 250: struct memrange *filo_map; ! 251: ! 252: linux_map = params->e820_map; ! 253: filo_map = info->memrange; ! 254: for (i = 0; i < info->n_memranges; i++, linux_map++, filo_map++) { ! 255: if (i < E820MAX) { ! 256: /* Convert to BIOS e820 style */ ! 257: linux_map->addr = filo_map->base; ! 258: linux_map->size = filo_map->size; ! 259: linux_map->type = E820_RAM; ! 260: debug("%016Lx - %016Lx\n", linux_map->addr, ! 261: linux_map->addr + linux_map->size); ! 262: params->e820_map_nr = i+1; ! 263: } ! 264: ! 265: /* Find out top of RAM. XXX This ignores hole above 1MB */ ! 266: end = filo_map->base + filo_map->size; ! 267: if (end < (1ULL << 32)) { /* don't count memory above 4GB */ ! 268: if (end > ramtop) ! 269: ramtop = (uint32_t) end; ! 270: } ! 271: } ! 272: debug("ramtop=%#x\n", ramtop); ! 273: /* Size of memory above 1MB in KB */ ! 274: params->alt_mem_k = (ramtop - (1<<20)) >> 10; ! 275: /* old style, 64MB max */ ! 276: if (ramtop >= (64<<20)) ! 277: params->ext_mem_k = (63<<10); ! 278: else ! 279: params->ext_mem_k = params->alt_mem_k; ! 280: debug("ext_mem_k=%d, alt_mem_k=%d\n", params->ext_mem_k, params->alt_mem_k); ! 281: } ! 282: ! 283: /* ! 284: * Parse command line ! 285: * Some parameters, like initrd=<file>, are not passed to kernel, ! 286: * we are responsible to process them. ! 287: * Parameters for kernel are copied to kern_cmdline. Returns name of initrd. ! 288: */ ! 289: static char *parse_command_line(const char *orig_cmdline, char *kern_cmdline) ! 290: { ! 291: const char *start, *sep, *end, *val; ! 292: char name[64]; ! 293: int len; ! 294: int k_len; ! 295: int to_kern; ! 296: char *initrd = 0; ! 297: int toolong = 0; ! 298: ! 299: forced_memsize = 0; ! 300: ! 301: if (!orig_cmdline) { ! 302: *kern_cmdline = 0; ! 303: return 0; ! 304: } ! 305: ! 306: k_len = 0; ! 307: debug("original command line: \"%s\"\n", orig_cmdline); ! 308: debug("kernel command line at %#lx\n", virt_to_phys(kern_cmdline)); ! 309: ! 310: start = orig_cmdline; ! 311: while (*start == ' ') ! 312: start++; ! 313: while (*start) { ! 314: end = strchr(start, ' '); ! 315: if (!end) ! 316: end = start + strlen(start); ! 317: sep = strchr(start, '='); ! 318: if (!sep || sep > end) ! 319: sep = end; ! 320: len = sep - start; ! 321: if (len >= sizeof(name)) ! 322: len = sizeof(name) - 1; ! 323: memcpy(name, start, len); ! 324: name[len] = 0; ! 325: ! 326: if (*sep == '=') { ! 327: val = sep + 1; ! 328: len = end - val; ! 329: } else { ! 330: val = 0; ! 331: len = 0; ! 332: } ! 333: ! 334: /* Only initrd= and mem= are handled here. vga= is not, ! 335: * which I believe is a paramter to the realmode part of Linux, ! 336: * which we don't execute. */ ! 337: if (strcmp(name, "initrd") == 0) { ! 338: if (!val) ! 339: printf("Missing filename to initrd parameter\n"); ! 340: else { ! 341: initrd = malloc(len + 1); ! 342: memcpy(initrd, val, len); ! 343: initrd[len] = 0; ! 344: debug("initrd=%s\n", initrd); ! 345: } ! 346: /* Don't pass this to kernel */ ! 347: to_kern = 0; ! 348: } else if (strcmp(name, "mem") == 0) { ! 349: if (!val) ! 350: printf("Missing value for mem parameter\n"); ! 351: else { ! 352: forced_memsize = strtoull_with_suffix(val, (char**)&val, 0); ! 353: if (forced_memsize == 0) ! 354: printf("Invalid mem option, ignored\n"); ! 355: if (val != end) { ! 356: printf("Garbage after mem=<size>, ignored\n"); ! 357: forced_memsize = 0; ! 358: } ! 359: debug("mem=%Lu\n", forced_memsize); ! 360: } ! 361: /* mem= is for both loader and kernel */ ! 362: to_kern = 1; ! 363: } else ! 364: to_kern = 1; ! 365: ! 366: if (to_kern) { ! 367: /* Copy to kernel command line buffer */ ! 368: if (k_len != 0) ! 369: kern_cmdline[k_len++] = ' '; /* put separator */ ! 370: len = end - start; ! 371: if (k_len + len >= COMMAND_LINE_SIZE) { ! 372: len = COMMAND_LINE_SIZE - k_len - 1; ! 373: if (!toolong) { ! 374: printf("Kernel command line is too long; truncated to " ! 375: "%d bytes\n", COMMAND_LINE_SIZE-1); ! 376: toolong = 1; ! 377: } ! 378: } ! 379: memcpy(kern_cmdline + k_len, start, len); ! 380: k_len += len; ! 381: } ! 382: ! 383: start = end; ! 384: while (*start == ' ') ! 385: start++; ! 386: } ! 387: kern_cmdline[k_len] = 0; ! 388: debug("kernel command line (%d bytes): \"%s\"\n", k_len, kern_cmdline); ! 389: ! 390: return initrd; ! 391: } ! 392: ! 393: /* Set command line location */ ! 394: static void set_command_line_loc(struct linux_params *params, ! 395: struct linux_header *hdr) ! 396: { ! 397: if (hdr->protocol_version >= 0x202) { ! 398: /* new style */ ! 399: params->cmd_line_ptr = COMMAND_LINE_LOC; ! 400: } else { ! 401: /* old style */ ! 402: params->cl_magic = CL_MAGIC_VALUE; ! 403: params->cl_offset = COMMAND_LINE_LOC - LINUX_PARAM_LOC; ! 404: } ! 405: } ! 406: ! 407: /* Load 32-bit part of kernel */ ! 408: static int load_linux_kernel(struct linux_header *hdr, uint32_t kern_addr) ! 409: { ! 410: uint32_t kern_offset, kern_size; ! 411: ! 412: if (hdr->setup_sects == 0) ! 413: hdr->setup_sects = 4; ! 414: kern_offset = (hdr->setup_sects + 1) * 512; ! 415: file_seek(kern_offset); ! 416: kern_size = file_size() - kern_offset; ! 417: debug("offset=%#x addr=%#x size=%#x\n", kern_offset, kern_addr, kern_size); ! 418: ! 419: #if 0 ! 420: if (using_devsize) { ! 421: printf("Attempt to load up to end of device as kernel; " ! 422: "specify the image size\n"); ! 423: return 0; ! 424: } ! 425: #endif ! 426: ! 427: printf("Loading kernel... "); ! 428: if (lfile_read(phys_to_virt(kern_addr), kern_size) != kern_size) { ! 429: printf("Can't read kernel\n"); ! 430: return 0; ! 431: } ! 432: printf("ok\n"); ! 433: ! 434: return kern_size; ! 435: } ! 436: ! 437: static int load_initrd(struct linux_header *hdr, struct sys_info *info, ! 438: uint32_t kern_end, struct linux_params *params, const char *initrd_file) ! 439: { ! 440: uint32_t max; ! 441: uint32_t start, end, size; ! 442: uint64_t forced; ! 443: extern char _start[], _end[]; ! 444: ! 445: if (!file_open(initrd_file)) { ! 446: printf("Can't open initrd: %s\n", initrd_file); ! 447: return -1; ! 448: } ! 449: ! 450: #if 0 ! 451: if (using_devsize) { ! 452: printf("Attempt to load up to end of device as initrd; " ! 453: "specify the image size\n"); ! 454: return -1; ! 455: } ! 456: #endif ! 457: ! 458: size = file_size(); ! 459: ! 460: ! 461: /* Find out the kernel's restriction on how high the initrd can be ! 462: * placed */ ! 463: if (hdr->protocol_version >= 0x203) ! 464: max = hdr->initrd_addr_max; ! 465: else ! 466: max = 0x38000000; /* Hardcoded value for older kernels */ ! 467: ! 468: /* FILO itself is at the top of RAM. (relocated) ! 469: * So, try putting initrd just below us. */ ! 470: end = virt_to_phys(_start); ! 471: if (end > max) ! 472: end = max; ! 473: ! 474: /* If "mem=" option is given, we have to put the initrd within ! 475: * the specified range. */ ! 476: if (forced_memsize) { ! 477: forced = forced_memsize; ! 478: if (forced > max) ! 479: forced = max; ! 480: /* If the "mem=" is lower, it's easy */ ! 481: if (forced <= end) ! 482: end = forced; ! 483: else { ! 484: /* Otherwise, see if we can put it above us */ ! 485: if (virt_to_phys(_end) + size <= forced) ! 486: end = forced; /* Ok */ ! 487: } ! 488: } ! 489: ! 490: start = end - size; ! 491: start &= ~0xfff; /* page align */ ! 492: end = start + size; ! 493: ! 494: debug("start=%#x end=%#x\n", start, end); ! 495: ! 496: if (start < kern_end) { ! 497: printf("Initrd is too big to fit in memory\n"); ! 498: return -1; ! 499: } ! 500: ! 501: printf("Loading initrd... "); ! 502: if (lfile_read(phys_to_virt(start), size) != size) { ! 503: printf("Can't read initrd\n"); ! 504: return -1; ! 505: } ! 506: printf("ok\n"); ! 507: ! 508: params->initrd_start = start; ! 509: params->initrd_size = size; ! 510: ! 511: return 0; ! 512: } ! 513: ! 514: static void hardware_setup(void) ! 515: { ! 516: /* Disable nmi */ ! 517: outb(0x80, 0x70); ! 518: ! 519: /* Make sure any coprocessor is properly reset.. */ ! 520: outb(0, 0xf0); ! 521: outb(0, 0xf1); ! 522: ! 523: /* we're getting screwed again and again by this problem of the 8259. ! 524: * so we're going to leave this lying around for inclusion into ! 525: * crt0.S on an as-needed basis. ! 526: * ! 527: * well, that went ok, I hope. Now we have to reprogram the interrupts :-( ! 528: * we put them right after the intel-reserved hardware interrupts, at ! 529: * int 0x20-0x2F. There they won't mess up anything. Sadly IBM really ! 530: * messed this up with the original PC, and they haven't been able to ! 531: * rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f, ! 532: * which is used for the internal hardware interrupts as well. We just ! 533: * have to reprogram the 8259's, and it isn't fun. ! 534: */ ! 535: ! 536: outb(0x11, 0x20); /* initialization sequence to 8259A-1 */ ! 537: outb(0x11, 0xA0); /* and to 8259A-2 */ ! 538: ! 539: outb(0x20, 0x21); /* start of hardware int's (0x20) */ ! 540: outb(0x28, 0xA1); /* start of hardware int's 2 (0x28) */ ! 541: ! 542: outb(0x04, 0x21); /* 8259-1 is master */ ! 543: outb(0x02, 0xA1); /* 8259-2 is slave */ ! 544: ! 545: outb(0x01, 0x21); /* 8086 mode for both */ ! 546: outb(0x01, 0xA1); ! 547: ! 548: outb(0xFF, 0xA1); /* mask off all interrupts for now */ ! 549: outb(0xFB, 0x21); /* mask all irq's but irq2 which is cascaded */ ! 550: } ! 551: ! 552: /* Start Linux */ ! 553: static int start_linux(uint32_t kern_addr, struct linux_params *params) ! 554: { ! 555: struct segment_desc *linux_gdt; ! 556: struct context *ctx; ! 557: //extern int cursor_x, cursor_y; ! 558: ! 559: ctx = init_context(phys_to_virt(STACK_LOC), 4096, 0); ! 560: ! 561: /* Linux expects GDT being in low memory */ ! 562: linux_gdt = phys_to_virt(GDT_LOC); ! 563: memset(linux_gdt, 0, 13*sizeof(struct segment_desc)); ! 564: /* Normal kernel code/data segments */ ! 565: linux_gdt[2] = gdt[FLAT_CODE]; ! 566: linux_gdt[3] = gdt[FLAT_DATA]; ! 567: /* 2.6 kernel uses 12 and 13, but head.S uses backward-compatible ! 568: * segments (2 and 3), so it SHOULD not be a problem. ! 569: * However, some distro kernels (eg. RH9) with backported threading ! 570: * patch use 12 and 13 also when booting... */ ! 571: linux_gdt[12] = gdt[FLAT_CODE]; ! 572: linux_gdt[13] = gdt[FLAT_DATA]; ! 573: ctx->gdt_base = GDT_LOC; ! 574: ctx->gdt_limit = 14*8-1; ! 575: ctx->cs = 0x10; ! 576: ctx->ds = 0x18; ! 577: ctx->es = 0x18; ! 578: ctx->fs = 0x18; ! 579: ctx->gs = 0x18; ! 580: ctx->ss = 0x18; ! 581: ! 582: /* Parameter location */ ! 583: ctx->esi = virt_to_phys(params); ! 584: ! 585: /* Entry point */ ! 586: ctx->eip = kern_addr; ! 587: ! 588: debug("eip=%#x\n", kern_addr); ! 589: printf("Jumping to entry point...\n"); ! 590: ! 591: #ifdef VGA_CONSOLE ! 592: /* Update VGA cursor position. ! 593: * This must be here because the printf changes the value! */ ! 594: params->orig_x = cursor_x; ! 595: params->orig_y = cursor_y; ! 596: #endif ! 597: ! 598: /* Go... */ ! 599: ctx = switch_to(ctx); ! 600: ! 601: /* It's impossible but... */ ! 602: printf("Returned with eax=%#x\n", ctx->eax); ! 603: ! 604: return ctx->eax; ! 605: } ! 606: ! 607: int linux_load(struct sys_info *info, const char *file, const char *cmdline) ! 608: { ! 609: struct linux_header hdr; ! 610: struct linux_params *params; ! 611: uint32_t kern_addr, kern_size; ! 612: char *initrd_file = 0; ! 613: ! 614: if (!file_open(file)) ! 615: return -1; ! 616: ! 617: kern_addr = load_linux_header(&hdr); ! 618: if (kern_addr == 0) ! 619: return LOADER_NOT_SUPPORT; ! 620: ! 621: params = phys_to_virt(LINUX_PARAM_LOC); ! 622: init_linux_params(params, &hdr); ! 623: set_memory_size(params, info); ! 624: initrd_file = parse_command_line(cmdline, phys_to_virt(COMMAND_LINE_LOC)); ! 625: set_command_line_loc(params, &hdr); ! 626: ! 627: kern_size = load_linux_kernel(&hdr, kern_addr); ! 628: if (kern_size == 0) { ! 629: if (initrd_file) ! 630: free(initrd_file); ! 631: return -1; ! 632: } ! 633: ! 634: if (initrd_file) { ! 635: if (load_initrd(&hdr, info, kern_addr+kern_size, params, initrd_file) ! 636: != 0) { ! 637: free(initrd_file); ! 638: return -1; ! 639: } ! 640: free(initrd_file); ! 641: } ! 642: ! 643: hardware_setup(); ! 644: ! 645: start_linux(kern_addr, params); ! 646: return 0; ! 647: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.