1*6d3ceb1dSskrll /* $NetBSD: main.c,v 1.1 2014/02/24 07:23:43 skrll Exp $ */
2*6d3ceb1dSskrll
3*6d3ceb1dSskrll /*
4*6d3ceb1dSskrll * Copyright (c) 2003 ITOH Yasufumi.
5*6d3ceb1dSskrll * All rights reserved.
6*6d3ceb1dSskrll *
7*6d3ceb1dSskrll * Redistribution and use in source and binary forms, with or without
8*6d3ceb1dSskrll * modification, are permitted provided that the following conditions
9*6d3ceb1dSskrll * are met:
10*6d3ceb1dSskrll * 1. Redistributions of source code must retain the above copyright
11*6d3ceb1dSskrll * notice, this list of conditions and the following disclaimer.
12*6d3ceb1dSskrll * 2. Redistributions in binary forms are unlimited.
13*6d3ceb1dSskrll *
14*6d3ceb1dSskrll * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS''
15*6d3ceb1dSskrll * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16*6d3ceb1dSskrll * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17*6d3ceb1dSskrll * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS
18*6d3ceb1dSskrll * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19*6d3ceb1dSskrll * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20*6d3ceb1dSskrll * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21*6d3ceb1dSskrll * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22*6d3ceb1dSskrll * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23*6d3ceb1dSskrll * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24*6d3ceb1dSskrll * THE POSSIBILITY OF SUCH DAMAGE.
25*6d3ceb1dSskrll */
26*6d3ceb1dSskrll
27*6d3ceb1dSskrll #include <sys/types.h>
28*6d3ceb1dSskrll #include <sys/param.h>
29*6d3ceb1dSskrll #include <ufs/ufs/dinode.h>
30*6d3ceb1dSskrll #include <sys/disklabel.h>
31*6d3ceb1dSskrll #include <sys/exec_elf.h>
32*6d3ceb1dSskrll #include "readufs.h"
33*6d3ceb1dSskrll
34*6d3ceb1dSskrll #define STACK_SIZE ((unsigned) (64*1024))
35*6d3ceb1dSskrll #define LOAD_ALIGN ((unsigned) 2048)
36*6d3ceb1dSskrll
37*6d3ceb1dSskrll #define PZ_MEM_BOOT 0x3d0
38*6d3ceb1dSskrll #define DEV_CLASS 0x2c
39*6d3ceb1dSskrll #define DEV_CL_MASK 0xf
40*6d3ceb1dSskrll #define DEV_CL_SEQU 0x2 /* sequential record access media */
41*6d3ceb1dSskrll
42*6d3ceb1dSskrll static char *hexstr(char *, unsigned);
43*6d3ceb1dSskrll void ipl_main(unsigned /*interactive*/, unsigned /*sptop*/, unsigned /*psw*/);
44*6d3ceb1dSskrll void load_file(const char *, uintptr_t /*loadadr*/, unsigned /*interactive*/,
45*6d3ceb1dSskrll int /*part*/);
46*6d3ceb1dSskrll void load_file_ino(ino32_t, const char *, uintptr_t /*loadadr*/,
47*6d3ceb1dSskrll unsigned /*interactive*/, int /*part*/);
48*6d3ceb1dSskrll
49*6d3ceb1dSskrll struct loadinfo {
50*6d3ceb1dSskrll void *sec_image;
51*6d3ceb1dSskrll unsigned sec_size;
52*6d3ceb1dSskrll #if 0
53*6d3ceb1dSskrll unsigned sec_pad;
54*6d3ceb1dSskrll #endif
55*6d3ceb1dSskrll unsigned entry_offset;
56*6d3ceb1dSskrll };
57*6d3ceb1dSskrll static inline void xi_elf32(struct loadinfo *, Elf32_Ehdr *);
58*6d3ceb1dSskrll static inline void xi_elf64(struct loadinfo *, Elf64_Ehdr *);
59*6d3ceb1dSskrll int xi_load(struct loadinfo *, void *);
60*6d3ceb1dSskrll
61*6d3ceb1dSskrll void reboot(void);
62*6d3ceb1dSskrll void halt(void);
63*6d3ceb1dSskrll void dispatch(unsigned /*interactive*/, unsigned /*top*/,
64*6d3ceb1dSskrll unsigned /*end*/, int /*part*/, unsigned /*entry*/);
65*6d3ceb1dSskrll void print(const char *);
66*6d3ceb1dSskrll void putch(int);
67*6d3ceb1dSskrll int getch(void);
68*6d3ceb1dSskrll int boot_input(void *, int /*len*/, int /*pos*/);
69*6d3ceb1dSskrll
70*6d3ceb1dSskrll /* to make generated code relocatable, do NOT mark them as const */
71*6d3ceb1dSskrll extern char str_seekseq[], str_bit_firmware[];
72*6d3ceb1dSskrll extern char str_crlf[], str_space[], str_rubout[];
73*6d3ceb1dSskrll extern char str_bootpart[], str_booting_part[];
74*6d3ceb1dSskrll extern char str_warn_2GB[], str_warn_unused[], str_nolabel[];
75*6d3ceb1dSskrll extern char str_filesystem[], str_nofs[];
76*6d3ceb1dSskrll extern char str_lookup[], str_loading[], str_at[], str_dddot[], str_done[];
77*6d3ceb1dSskrll extern char str_boot1[], str_boot2[], str_boot3[];
78*6d3ceb1dSskrll extern char str_noboot[];
79*6d3ceb1dSskrll extern char str_ukfmt[];
80*6d3ceb1dSskrll
81*6d3ceb1dSskrll #ifdef __GNUC__
82*6d3ceb1dSskrll #define memcpy(d, s, n) __builtin_memcpy(d, s, n)
83*6d3ceb1dSskrll #else
84*6d3ceb1dSskrll void *memcpy(void *, const void *, size_t);
85*6d3ceb1dSskrll #endif
86*6d3ceb1dSskrll void *memmove(void *, const void *, size_t);
87*6d3ceb1dSskrll
88*6d3ceb1dSskrll /* disklabel */
89*6d3ceb1dSskrll union {
90*6d3ceb1dSskrll char dklsec[512];
91*6d3ceb1dSskrll struct disklabel dkl; /* to ensure alignment */
92*6d3ceb1dSskrll } labelsector;
93*6d3ceb1dSskrll #define dklabel (*(struct disklabel *)(labelsector.dklsec + LABELOFFSET))
94*6d3ceb1dSskrll
95*6d3ceb1dSskrll unsigned offset_raw_read;
96*6d3ceb1dSskrll
97*6d3ceb1dSskrll extern char diskbuf[2048];
98*6d3ceb1dSskrll #define BLK_PER_READ 4
99*6d3ceb1dSskrll #define MASK_BLK_PER_READ (BLK_PER_READ - 1)
100*6d3ceb1dSskrll
101*6d3ceb1dSskrll void
RAW_READ(void * buf,daddr_t blkpos,size_t bytelen)102*6d3ceb1dSskrll RAW_READ(void *buf, daddr_t blkpos, size_t bytelen)
103*6d3ceb1dSskrll {
104*6d3ceb1dSskrll char *b = buf;
105*6d3ceb1dSskrll size_t off, readlen;
106*6d3ceb1dSskrll int devoff;
107*6d3ceb1dSskrll static int prvdevoff = -dbtob(BLK_PER_READ);
108*6d3ceb1dSskrll int pos;
109*6d3ceb1dSskrll
110*6d3ceb1dSskrll for ( ; bytelen > 0; b += readlen, bytelen -= readlen) {
111*6d3ceb1dSskrll /*
112*6d3ceb1dSskrll * read 2KB, avoiding unneeded read
113*6d3ceb1dSskrll */
114*6d3ceb1dSskrll devoff = dbtob(blkpos & ~MASK_BLK_PER_READ) + offset_raw_read;
115*6d3ceb1dSskrll if (prvdevoff != devoff) {
116*6d3ceb1dSskrll #if 1 /* supports sequential media */
117*6d3ceb1dSskrll if ((*(unsigned *)(PZ_MEM_BOOT+DEV_CLASS) & DEV_CL_MASK)
118*6d3ceb1dSskrll == DEV_CL_SEQU) {
119*6d3ceb1dSskrll /*
120*6d3ceb1dSskrll * sequential media
121*6d3ceb1dSskrll * -- read sequentially or rewind
122*6d3ceb1dSskrll */
123*6d3ceb1dSskrll pos = prvdevoff + dbtob(BLK_PER_READ);
124*6d3ceb1dSskrll if (devoff < pos)
125*6d3ceb1dSskrll pos = 0; /* rewind */
126*6d3ceb1dSskrll
127*6d3ceb1dSskrll /* "repositioning media...\r\n" */
128*6d3ceb1dSskrll if (devoff - pos > 512 * 1024)
129*6d3ceb1dSskrll print(str_seekseq);
130*6d3ceb1dSskrll
131*6d3ceb1dSskrll for (; pos < devoff; pos += dbtob(BLK_PER_READ))
132*6d3ceb1dSskrll boot_input(diskbuf,
133*6d3ceb1dSskrll dbtob(BLK_PER_READ), pos);
134*6d3ceb1dSskrll }
135*6d3ceb1dSskrll #endif
136*6d3ceb1dSskrll prvdevoff = devoff;
137*6d3ceb1dSskrll boot_input(diskbuf, dbtob(BLK_PER_READ), devoff);
138*6d3ceb1dSskrll }
139*6d3ceb1dSskrll /*
140*6d3ceb1dSskrll * copy specified size to the destination
141*6d3ceb1dSskrll */
142*6d3ceb1dSskrll off = dbtob(blkpos & MASK_BLK_PER_READ),
143*6d3ceb1dSskrll readlen = dbtob(BLK_PER_READ) - off;
144*6d3ceb1dSskrll if (readlen > bytelen)
145*6d3ceb1dSskrll readlen = bytelen;
146*6d3ceb1dSskrll memcpy(b, diskbuf + off, readlen);
147*6d3ceb1dSskrll blkpos = (blkpos & ~MASK_BLK_PER_READ) + BLK_PER_READ;
148*6d3ceb1dSskrll }
149*6d3ceb1dSskrll }
150*6d3ceb1dSskrll
151*6d3ceb1dSskrll /*
152*6d3ceb1dSskrll * convert number to hex string
153*6d3ceb1dSskrll * buf must have enough space
154*6d3ceb1dSskrll */
155*6d3ceb1dSskrll static char *
hexstr(char * buf,unsigned val)156*6d3ceb1dSskrll hexstr(char *buf, unsigned val)
157*6d3ceb1dSskrll {
158*6d3ceb1dSskrll unsigned v;
159*6d3ceb1dSskrll char rev[16];
160*6d3ceb1dSskrll char *r = rev, *b = buf;
161*6d3ceb1dSskrll
162*6d3ceb1dSskrll /* inverse order */
163*6d3ceb1dSskrll do {
164*6d3ceb1dSskrll v = val & 0xf;
165*6d3ceb1dSskrll *r++ = (v <= 9) ? '0' + v : 'a' - 10 + v;
166*6d3ceb1dSskrll val >>= 4;
167*6d3ceb1dSskrll } while (val);
168*6d3ceb1dSskrll
169*6d3ceb1dSskrll /* reverse string */
170*6d3ceb1dSskrll while (r > rev)
171*6d3ceb1dSskrll *b++ = *--r;
172*6d3ceb1dSskrll
173*6d3ceb1dSskrll *b = '\0';
174*6d3ceb1dSskrll return buf;
175*6d3ceb1dSskrll }
176*6d3ceb1dSskrll
177*6d3ceb1dSskrll void
ipl_main(unsigned interactive,unsigned sptop,unsigned psw)178*6d3ceb1dSskrll ipl_main(unsigned interactive, unsigned sptop, unsigned psw)
179*6d3ceb1dSskrll /* interactive: parameters from PDC */
180*6d3ceb1dSskrll /* sptop: value of sp on function entry */
181*6d3ceb1dSskrll /* psw: PSW on startup */
182*6d3ceb1dSskrll {
183*6d3ceb1dSskrll char buf[32];
184*6d3ceb1dSskrll int part = 0; /* default partition "a" */
185*6d3ceb1dSskrll unsigned secsz, partoff, partsz;
186*6d3ceb1dSskrll int c, c1;
187*6d3ceb1dSskrll uintptr_t loadadr;
188*6d3ceb1dSskrll
189*6d3ceb1dSskrll #if 0
190*6d3ceb1dSskrll print(hexstr(buf, interactive));
191*6d3ceb1dSskrll print(str_crlf);
192*6d3ceb1dSskrll print(hexstr(buf, sptop));
193*6d3ceb1dSskrll print(str_crlf);
194*6d3ceb1dSskrll print(hexstr(buf, psw));
195*6d3ceb1dSskrll print(str_crlf);
196*6d3ceb1dSskrll #endif
197*6d3ceb1dSskrll
198*6d3ceb1dSskrll print(hexstr(buf, (psw & 0x08000000) ? (unsigned) 0x64 : 0x32));
199*6d3ceb1dSskrll print(str_bit_firmware); /* "bit firmware\r\n" */
200*6d3ceb1dSskrll
201*6d3ceb1dSskrll /*
202*6d3ceb1dSskrll * check disklabel
203*6d3ceb1dSskrll * (dklabel has disklabel on startup)
204*6d3ceb1dSskrll */
205*6d3ceb1dSskrll if (dklabel.d_magic == DISKMAGIC && (secsz = dklabel.d_secsize) != 0) {
206*6d3ceb1dSskrll /*
207*6d3ceb1dSskrll * select boot partition
208*6d3ceb1dSskrll */
209*6d3ceb1dSskrll if (interactive) {
210*6d3ceb1dSskrll select_partition:
211*6d3ceb1dSskrll /* "boot partition (a-p, ! to reboot) [a]:" */
212*6d3ceb1dSskrll print(str_bootpart);
213*6d3ceb1dSskrll part = 0; /* default partition "a" */
214*6d3ceb1dSskrll c1 = 0;
215*6d3ceb1dSskrll while ((c = getch()) >= 0) {
216*6d3ceb1dSskrll switch (c) {
217*6d3ceb1dSskrll case '\n':
218*6d3ceb1dSskrll case '\r':
219*6d3ceb1dSskrll goto break_while;
220*6d3ceb1dSskrll case '\b':
221*6d3ceb1dSskrll case '\177':
222*6d3ceb1dSskrll if (c1) {
223*6d3ceb1dSskrll print(str_rubout);
224*6d3ceb1dSskrll part = c1 = 0;
225*6d3ceb1dSskrll }
226*6d3ceb1dSskrll break;
227*6d3ceb1dSskrll case '!': /* reset */
228*6d3ceb1dSskrll if (c1 == 0) {
229*6d3ceb1dSskrll part = -1;
230*6d3ceb1dSskrll goto echoback;
231*6d3ceb1dSskrll }
232*6d3ceb1dSskrll break;
233*6d3ceb1dSskrll default:
234*6d3ceb1dSskrll if (c1 == 0 && c >= 'a' && c <= 'p') {
235*6d3ceb1dSskrll part = c - 'a';
236*6d3ceb1dSskrll echoback:
237*6d3ceb1dSskrll putch(c);
238*6d3ceb1dSskrll c1 = 1;
239*6d3ceb1dSskrll }
240*6d3ceb1dSskrll break;
241*6d3ceb1dSskrll }
242*6d3ceb1dSskrll }
243*6d3ceb1dSskrll break_while:
244*6d3ceb1dSskrll if (part == -1)
245*6d3ceb1dSskrll return; /* reset */
246*6d3ceb1dSskrll }
247*6d3ceb1dSskrll
248*6d3ceb1dSskrll /*
249*6d3ceb1dSskrll * "\r\nbooting from partition _\r\n"
250*6d3ceb1dSskrll */
251*6d3ceb1dSskrll str_booting_part[25] = 'a' + part;
252*6d3ceb1dSskrll print(str_booting_part);
253*6d3ceb1dSskrll
254*6d3ceb1dSskrll partoff = dklabel.d_partitions[part].p_offset;
255*6d3ceb1dSskrll partsz = dklabel.d_partitions[part].p_size;
256*6d3ceb1dSskrll
257*6d3ceb1dSskrll if (part >= (int) dklabel.d_npartitions || partsz == 0) {
258*6d3ceb1dSskrll print(str_warn_unused); /* "unused partition\r\n" */
259*6d3ceb1dSskrll goto select_partition;
260*6d3ceb1dSskrll }
261*6d3ceb1dSskrll
262*6d3ceb1dSskrll /* boot partition must be below 2GB */
263*6d3ceb1dSskrll if (partoff + partsz > ((unsigned)2*1024*1024*1024) / secsz) {
264*6d3ceb1dSskrll /* "boot partition exceeds 2GB boundary\r\n" */
265*6d3ceb1dSskrll print(str_warn_2GB);
266*6d3ceb1dSskrll goto select_partition;
267*6d3ceb1dSskrll }
268*6d3ceb1dSskrll
269*6d3ceb1dSskrll /*
270*6d3ceb1dSskrll * following device accesses are only in the partition
271*6d3ceb1dSskrll */
272*6d3ceb1dSskrll offset_raw_read = partoff * secsz;
273*6d3ceb1dSskrll } else {
274*6d3ceb1dSskrll /*
275*6d3ceb1dSskrll * no disklabel --- assume the whole of the device
276*6d3ceb1dSskrll * is a filesystem
277*6d3ceb1dSskrll */
278*6d3ceb1dSskrll print(str_nolabel); /* "no disklabel\r\n" */
279*6d3ceb1dSskrll }
280*6d3ceb1dSskrll
281*6d3ceb1dSskrll if (ufs_init()) {
282*6d3ceb1dSskrll print(str_nofs); /* "no filesystem found\r\n" */
283*6d3ceb1dSskrll return;
284*6d3ceb1dSskrll }
285*6d3ceb1dSskrll str_filesystem[12] = (ufs_info.fstype == UFSTYPE_FFS) ? 'F' : 'L';
286*6d3ceb1dSskrll print(str_filesystem); /* "filesystem: _FS\r\n" */
287*6d3ceb1dSskrll
288*6d3ceb1dSskrll loadadr = (sptop + STACK_SIZE + LOAD_ALIGN - 1) & (-LOAD_ALIGN);
289*6d3ceb1dSskrll load_file(str_boot1, loadadr, interactive, part); /* "boot.hp700" */
290*6d3ceb1dSskrll load_file(str_boot2, loadadr, interactive, part); /* "boot" */
291*6d3ceb1dSskrll load_file(str_boot3, loadadr, interactive, part); /* "usr/mdec/boot" */
292*6d3ceb1dSskrll
293*6d3ceb1dSskrll print(str_noboot); /* "no secondary boot found\r\n" */
294*6d3ceb1dSskrll }
295*6d3ceb1dSskrll
296*6d3ceb1dSskrll void
load_file(const char * path,uintptr_t loadadr,unsigned interactive,int part)297*6d3ceb1dSskrll load_file(const char *path, uintptr_t loadadr, unsigned interactive, int part)
298*6d3ceb1dSskrll {
299*6d3ceb1dSskrll
300*6d3ceb1dSskrll /* look-up the file */
301*6d3ceb1dSskrll print(str_lookup); /* "looking up " */
302*6d3ceb1dSskrll print(path);
303*6d3ceb1dSskrll print(str_crlf);
304*6d3ceb1dSskrll load_file_ino(ufs_lookup_path(path), path, loadadr, interactive, part);
305*6d3ceb1dSskrll }
306*6d3ceb1dSskrll
307*6d3ceb1dSskrll void
load_file_ino(ino32_t ino,const char * fn,uintptr_t loadadr,unsigned interactive,int part)308*6d3ceb1dSskrll load_file_ino(ino32_t ino, const char *fn, uintptr_t loadadr, unsigned interactive, int part)
309*6d3ceb1dSskrll /* fn: for message only */
310*6d3ceb1dSskrll {
311*6d3ceb1dSskrll union ufs_dinode dinode;
312*6d3ceb1dSskrll size_t sz;
313*6d3ceb1dSskrll struct loadinfo inf;
314*6d3ceb1dSskrll char buf[32];
315*6d3ceb1dSskrll
316*6d3ceb1dSskrll if (ino == 0 || ufs_get_inode(ino, &dinode))
317*6d3ceb1dSskrll return; /* not found */
318*6d3ceb1dSskrll
319*6d3ceb1dSskrll print(str_loading); /* "loading " */
320*6d3ceb1dSskrll print(fn);
321*6d3ceb1dSskrll print(str_at); /* " at 0x" */
322*6d3ceb1dSskrll print(hexstr(buf, loadadr));
323*6d3ceb1dSskrll print(str_dddot); /* "..." */
324*6d3ceb1dSskrll
325*6d3ceb1dSskrll sz = DI_SIZE(&dinode);
326*6d3ceb1dSskrll ufs_read(&dinode, (void *) loadadr, 0, sz);
327*6d3ceb1dSskrll
328*6d3ceb1dSskrll print(str_done); /* "done\r\n" */
329*6d3ceb1dSskrll
330*6d3ceb1dSskrll /* digest executable format */
331*6d3ceb1dSskrll inf.sec_size = sz;
332*6d3ceb1dSskrll inf.entry_offset = 0;
333*6d3ceb1dSskrll if (xi_load(&inf, (void *) loadadr)) {
334*6d3ceb1dSskrll print(fn);
335*6d3ceb1dSskrll print(str_ukfmt); /* ": unknown format -- exec from top\r\n" */
336*6d3ceb1dSskrll }
337*6d3ceb1dSskrll
338*6d3ceb1dSskrll /* pass control to the secondary boot */
339*6d3ceb1dSskrll dispatch(interactive, loadadr, loadadr + inf.sec_size, part,
340*6d3ceb1dSskrll loadadr + inf.entry_offset);
341*6d3ceb1dSskrll }
342*6d3ceb1dSskrll
343*6d3ceb1dSskrll /*
344*6d3ceb1dSskrll * fill in loading information from an ELF executable
345*6d3ceb1dSskrll */
346*6d3ceb1dSskrll static inline void
xi_elf32(struct loadinfo * inf,Elf32_Ehdr * hdr)347*6d3ceb1dSskrll xi_elf32(struct loadinfo *inf, Elf32_Ehdr *hdr)
348*6d3ceb1dSskrll {
349*6d3ceb1dSskrll char *top = (void *) hdr;
350*6d3ceb1dSskrll Elf32_Phdr *ph;
351*6d3ceb1dSskrll
352*6d3ceb1dSskrll /* text + data, bss */
353*6d3ceb1dSskrll ph = (void *) (top + hdr->e_phoff);
354*6d3ceb1dSskrll inf->sec_image = top + ph->p_offset;
355*6d3ceb1dSskrll inf->sec_size = ph->p_filesz;
356*6d3ceb1dSskrll #if 0
357*6d3ceb1dSskrll inf->sec_pad = ph->p_memsz - ph->p_filesz;
358*6d3ceb1dSskrll #endif
359*6d3ceb1dSskrll /* entry */
360*6d3ceb1dSskrll inf->entry_offset = hdr->e_entry - ph->p_vaddr;
361*6d3ceb1dSskrll }
362*6d3ceb1dSskrll
363*6d3ceb1dSskrll static inline void
xi_elf64(struct loadinfo * inf,Elf64_Ehdr * hdr)364*6d3ceb1dSskrll xi_elf64(struct loadinfo *inf, Elf64_Ehdr *hdr)
365*6d3ceb1dSskrll {
366*6d3ceb1dSskrll char *top = (void *) hdr;
367*6d3ceb1dSskrll Elf64_Phdr *ph;
368*6d3ceb1dSskrll
369*6d3ceb1dSskrll /*
370*6d3ceb1dSskrll * secondary boot is not so large, so 32bit (unsigned) arithmetic
371*6d3ceb1dSskrll * is enough
372*6d3ceb1dSskrll */
373*6d3ceb1dSskrll /* text + data, bss */
374*6d3ceb1dSskrll ph = (void *) (top + (unsigned) hdr->e_phoff);
375*6d3ceb1dSskrll inf->sec_image = top + (unsigned) ph->p_offset;
376*6d3ceb1dSskrll inf->sec_size = (unsigned) ph->p_filesz;
377*6d3ceb1dSskrll #if 0
378*6d3ceb1dSskrll inf->sec_pad = (unsigned) ph->p_memsz - (unsigned) ph->p_filesz;
379*6d3ceb1dSskrll #endif
380*6d3ceb1dSskrll /* entry */
381*6d3ceb1dSskrll inf->entry_offset = (unsigned) hdr->e_entry - (unsigned) ph->p_vaddr;
382*6d3ceb1dSskrll }
383*6d3ceb1dSskrll
384*6d3ceb1dSskrll int
xi_load(struct loadinfo * inf,void * buf)385*6d3ceb1dSskrll xi_load(struct loadinfo *inf, void *buf)
386*6d3ceb1dSskrll {
387*6d3ceb1dSskrll Elf32_Ehdr *e32hdr = buf;
388*6d3ceb1dSskrll Elf64_Ehdr *e64hdr = buf;
389*6d3ceb1dSskrll uint16_t class_data;
390*6d3ceb1dSskrll
391*6d3ceb1dSskrll /*
392*6d3ceb1dSskrll * check ELF header
393*6d3ceb1dSskrll * (optimized assuming big endian byte order)
394*6d3ceb1dSskrll */
395*6d3ceb1dSskrll /* ELF magic */
396*6d3ceb1dSskrll if (*(uint32_t *)&e32hdr->e_ident[EI_MAG0] !=
397*6d3ceb1dSskrll (ELFMAG0 << 24 | ELFMAG1 << 16 | ELFMAG2 << 8 | ELFMAG3) ||
398*6d3ceb1dSskrll e32hdr->e_ident[EI_VERSION] != EV_CURRENT)
399*6d3ceb1dSskrll return 1; /* Not an ELF */
400*6d3ceb1dSskrll
401*6d3ceb1dSskrll /* file and machine type */
402*6d3ceb1dSskrll if (*(uint32_t *)&e32hdr->e_type != (ET_EXEC << 16 | EM_PARISC))
403*6d3ceb1dSskrll return 1; /* Not an executable / Wrong architecture */
404*6d3ceb1dSskrll
405*6d3ceb1dSskrll if ((class_data = *(uint16_t *)&e32hdr->e_ident[EI_CLASS]) ==
406*6d3ceb1dSskrll (ELFCLASS32 << 8 | ELFDATA2MSB)) {
407*6d3ceb1dSskrll
408*6d3ceb1dSskrll /* support one section executable (ld -N) only */
409*6d3ceb1dSskrll if (e32hdr->e_phnum != 1)
410*6d3ceb1dSskrll return 1; /* Wrong number of loading sections */
411*6d3ceb1dSskrll
412*6d3ceb1dSskrll /* fill in loading information */
413*6d3ceb1dSskrll xi_elf32(inf, e32hdr);
414*6d3ceb1dSskrll
415*6d3ceb1dSskrll } else if (class_data == (ELFCLASS64 << 8 | ELFDATA2MSB)) {
416*6d3ceb1dSskrll
417*6d3ceb1dSskrll /* support one section executable (ld -N) only */
418*6d3ceb1dSskrll if (e64hdr->e_phnum != 1)
419*6d3ceb1dSskrll return 1; /* Wrong number of loading sections */
420*6d3ceb1dSskrll
421*6d3ceb1dSskrll /* fill in loading information */
422*6d3ceb1dSskrll xi_elf64(inf, e64hdr);
423*6d3ceb1dSskrll
424*6d3ceb1dSskrll } else
425*6d3ceb1dSskrll return 1; /* Not a 32bit or 64bit ELF */
426*6d3ceb1dSskrll
427*6d3ceb1dSskrll /* move text + data to the top address */
428*6d3ceb1dSskrll memmove(buf, inf->sec_image, inf->sec_size);
429*6d3ceb1dSskrll
430*6d3ceb1dSskrll #if 0 /* XXX bss clear is done by the secondary boot itself */
431*6d3ceb1dSskrll memset((char *) buf + inf->sec_size, 0, inf->sec_pad);
432*6d3ceb1dSskrll #endif
433*6d3ceb1dSskrll
434*6d3ceb1dSskrll return 0;
435*6d3ceb1dSskrll }
436