Annotation of qemu/roms/openbios/arch/sparc64/linux_load.c, revision 1.1

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=%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 */
        !           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=%#llx\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:     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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.