PageRenderTime 27ms CodeModel.GetById 16ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/ia64/hp/sim/boot/bootloader.c

https://bitbucket.org/evzijst/gittest
C | 176 lines | 125 code | 30 blank | 21 comment | 26 complexity | 7cf7c0483f35d8704ff4c107f7182fdb MD5 | raw file
  1/*
  2 * arch/ia64/hp/sim/boot/bootloader.c
  3 *
  4 * Loads an ELF kernel.
  5 *
  6 * Copyright (C) 1998-2003 Hewlett-Packard Co
  7 *	David Mosberger-Tang <davidm@hpl.hp.com>
  8 *	Stephane Eranian <eranian@hpl.hp.com>
  9 *
 10 * 01/07/99 S.Eranian modified to pass command line arguments to kernel
 11 */
 12struct task_struct;	/* forward declaration for elf.h */
 13
 14#include <linux/config.h>
 15#include <linux/elf.h>
 16#include <linux/init.h>
 17#include <linux/kernel.h>
 18
 19#include <asm/elf.h>
 20#include <asm/intrinsics.h>
 21#include <asm/pal.h>
 22#include <asm/pgtable.h>
 23#include <asm/sal.h>
 24#include <asm/system.h>
 25
 26#include "ssc.h"
 27
 28struct disk_req {
 29	unsigned long addr;
 30	unsigned len;
 31};
 32
 33struct disk_stat {
 34	int fd;
 35	unsigned count;
 36};
 37
 38extern void jmp_to_kernel (unsigned long bp, unsigned long e_entry);
 39extern struct ia64_boot_param *sys_fw_init (const char *args, int arglen);
 40extern void debug_break (void);
 41
 42static void
 43cons_write (const char *buf)
 44{
 45	unsigned long ch;
 46
 47	while ((ch = *buf++) != '\0') {
 48		ssc(ch, 0, 0, 0, SSC_PUTCHAR);
 49		if (ch == '\n')
 50		  ssc('\r', 0, 0, 0, SSC_PUTCHAR);
 51	}
 52}
 53
 54#define MAX_ARGS 32
 55
 56void
 57start_bootloader (void)
 58{
 59	static char mem[4096];
 60	static char buffer[1024];
 61	unsigned long off;
 62	int fd, i;
 63	struct disk_req req;
 64	struct disk_stat stat;
 65	struct elfhdr *elf;
 66	struct elf_phdr *elf_phdr;	/* program header */
 67	unsigned long e_entry, e_phoff, e_phnum;
 68	register struct ia64_boot_param *bp;
 69	char *kpath, *args;
 70	long arglen = 0;
 71
 72	ssc(0, 0, 0, 0, SSC_CONSOLE_INIT);
 73
 74	/*
 75	 * S.Eranian: extract the commandline argument from the simulator
 76	 *
 77	 * The expected format is as follows:
 78         *
 79	 *	kernelname args...
 80	 *
 81	 * Both are optional but you can't have the second one without the first.
 82	 */
 83	arglen = ssc((long) buffer, 0, 0, 0, SSC_GET_ARGS);
 84
 85	kpath = "vmlinux";
 86	args = buffer;
 87	if (arglen > 0) {
 88		kpath = buffer;
 89		while (*args != ' ' && *args != '\0')
 90			++args, --arglen;
 91		if (*args == ' ')
 92			*args++ = '\0', --arglen;
 93	}
 94
 95	if (arglen <= 0) {
 96		args = "";
 97		arglen = 1;
 98	}
 99
100	fd = ssc((long) kpath, 1, 0, 0, SSC_OPEN);
101
102	if (fd < 0) {
103		cons_write(kpath);
104		cons_write(": file not found, reboot now\n");
105		for(;;);
106	}
107	stat.fd = fd;
108	off = 0;
109
110	req.len = sizeof(mem);
111	req.addr = (long) mem;
112	ssc(fd, 1, (long) &req, off, SSC_READ);
113	ssc((long) &stat, 0, 0, 0, SSC_WAIT_COMPLETION);
114
115	elf = (struct elfhdr *) mem;
116	if (elf->e_ident[0] == 0x7f && strncmp(elf->e_ident + 1, "ELF", 3) != 0) {
117		cons_write("not an ELF file\n");
118		return;
119	}
120	if (elf->e_type != ET_EXEC) {
121		cons_write("not an ELF executable\n");
122		return;
123	}
124	if (!elf_check_arch(elf)) {
125		cons_write("kernel not for this processor\n");
126		return;
127	}
128
129	e_entry = elf->e_entry;
130	e_phnum = elf->e_phnum;
131	e_phoff = elf->e_phoff;
132
133	cons_write("loading ");
134	cons_write(kpath);
135	cons_write("...\n");
136
137	for (i = 0; i < e_phnum; ++i) {
138		req.len = sizeof(*elf_phdr);
139		req.addr = (long) mem;
140		ssc(fd, 1, (long) &req, e_phoff, SSC_READ);
141		ssc((long) &stat, 0, 0, 0, SSC_WAIT_COMPLETION);
142		if (stat.count != sizeof(*elf_phdr)) {
143			cons_write("failed to read phdr\n");
144			return;
145		}
146		e_phoff += sizeof(*elf_phdr);
147
148		elf_phdr = (struct elf_phdr *) mem;
149
150		if (elf_phdr->p_type != PT_LOAD)
151			continue;
152
153		req.len = elf_phdr->p_filesz;
154		req.addr = __pa(elf_phdr->p_paddr);
155		ssc(fd, 1, (long) &req, elf_phdr->p_offset, SSC_READ);
156		ssc((long) &stat, 0, 0, 0, SSC_WAIT_COMPLETION);
157		memset((char *)__pa(elf_phdr->p_paddr) + elf_phdr->p_filesz, 0,
158		       elf_phdr->p_memsz - elf_phdr->p_filesz);
159	}
160	ssc(fd, 0, 0, 0, SSC_CLOSE);
161
162	cons_write("starting kernel...\n");
163
164	/* fake an I/O base address: */
165	ia64_setreg(_IA64_REG_AR_KR0, 0xffffc000000UL);
166
167	bp = sys_fw_init(args, arglen);
168
169	ssc(0, (long) kpath, 0, 0, SSC_LOAD_SYMBOLS);
170
171	debug_break();
172	jmp_to_kernel((unsigned long) bp, e_entry);
173
174	cons_write("kernel returned!\n");
175	ssc(-1, 0, 0, 0, SSC_EXIT);
176}