Path: blob/master/arch/ia64/hp/sim/boot/bootloader.c
15159 views
/*1* arch/ia64/hp/sim/boot/bootloader.c2*3* Loads an ELF kernel.4*5* Copyright (C) 1998-2003 Hewlett-Packard Co6* David Mosberger-Tang <[email protected]>7* Stephane Eranian <[email protected]>8*9* 01/07/99 S.Eranian modified to pass command line arguments to kernel10*/11struct task_struct; /* forward declaration for elf.h */1213#include <linux/elf.h>14#include <linux/init.h>15#include <linux/kernel.h>1617#include <asm/elf.h>18#include <asm/intrinsics.h>19#include <asm/pal.h>20#include <asm/pgtable.h>21#include <asm/sal.h>22#include <asm/system.h>2324#include "ssc.h"2526struct disk_req {27unsigned long addr;28unsigned len;29};3031struct disk_stat {32int fd;33unsigned count;34};3536extern void jmp_to_kernel (unsigned long bp, unsigned long e_entry);37extern struct ia64_boot_param *sys_fw_init (const char *args, int arglen);38extern void debug_break (void);3940static void41cons_write (const char *buf)42{43unsigned long ch;4445while ((ch = *buf++) != '\0') {46ssc(ch, 0, 0, 0, SSC_PUTCHAR);47if (ch == '\n')48ssc('\r', 0, 0, 0, SSC_PUTCHAR);49}50}5152#define MAX_ARGS 325354void55start_bootloader (void)56{57static char mem[4096];58static char buffer[1024];59unsigned long off;60int fd, i;61struct disk_req req;62struct disk_stat stat;63struct elfhdr *elf;64struct elf_phdr *elf_phdr; /* program header */65unsigned long e_entry, e_phoff, e_phnum;66register struct ia64_boot_param *bp;67char *kpath, *args;68long arglen = 0;6970ssc(0, 0, 0, 0, SSC_CONSOLE_INIT);7172/*73* S.Eranian: extract the commandline argument from the simulator74*75* The expected format is as follows:76*77* kernelname args...78*79* Both are optional but you can't have the second one without the first.80*/81arglen = ssc((long) buffer, 0, 0, 0, SSC_GET_ARGS);8283kpath = "vmlinux";84args = buffer;85if (arglen > 0) {86kpath = buffer;87while (*args != ' ' && *args != '\0')88++args, --arglen;89if (*args == ' ')90*args++ = '\0', --arglen;91}9293if (arglen <= 0) {94args = "";95arglen = 1;96}9798fd = ssc((long) kpath, 1, 0, 0, SSC_OPEN);99100if (fd < 0) {101cons_write(kpath);102cons_write(": file not found, reboot now\n");103for(;;);104}105stat.fd = fd;106off = 0;107108req.len = sizeof(mem);109req.addr = (long) mem;110ssc(fd, 1, (long) &req, off, SSC_READ);111ssc((long) &stat, 0, 0, 0, SSC_WAIT_COMPLETION);112113elf = (struct elfhdr *) mem;114if (elf->e_ident[0] == 0x7f && strncmp(elf->e_ident + 1, "ELF", 3) != 0) {115cons_write("not an ELF file\n");116return;117}118if (elf->e_type != ET_EXEC) {119cons_write("not an ELF executable\n");120return;121}122if (!elf_check_arch(elf)) {123cons_write("kernel not for this processor\n");124return;125}126127e_entry = elf->e_entry;128e_phnum = elf->e_phnum;129e_phoff = elf->e_phoff;130131cons_write("loading ");132cons_write(kpath);133cons_write("...\n");134135for (i = 0; i < e_phnum; ++i) {136req.len = sizeof(*elf_phdr);137req.addr = (long) mem;138ssc(fd, 1, (long) &req, e_phoff, SSC_READ);139ssc((long) &stat, 0, 0, 0, SSC_WAIT_COMPLETION);140if (stat.count != sizeof(*elf_phdr)) {141cons_write("failed to read phdr\n");142return;143}144e_phoff += sizeof(*elf_phdr);145146elf_phdr = (struct elf_phdr *) mem;147148if (elf_phdr->p_type != PT_LOAD)149continue;150151req.len = elf_phdr->p_filesz;152req.addr = __pa(elf_phdr->p_paddr);153ssc(fd, 1, (long) &req, elf_phdr->p_offset, SSC_READ);154ssc((long) &stat, 0, 0, 0, SSC_WAIT_COMPLETION);155memset((char *)__pa(elf_phdr->p_paddr) + elf_phdr->p_filesz, 0,156elf_phdr->p_memsz - elf_phdr->p_filesz);157}158ssc(fd, 0, 0, 0, SSC_CLOSE);159160cons_write("starting kernel...\n");161162/* fake an I/O base address: */163ia64_setreg(_IA64_REG_AR_KR0, 0xffffc000000UL);164165bp = sys_fw_init(args, arglen);166167ssc(0, (long) kpath, 0, 0, SSC_LOAD_SYMBOLS);168169debug_break();170jmp_to_kernel((unsigned long) bp, e_entry);171172cons_write("kernel returned!\n");173ssc(-1, 0, 0, 0, SSC_EXIT);174}175176177