2 * Copyright (c) 1998 Robert Nordier
4 * Copyright (c) 2001 Robert Drehmel
7 * Redistribution and use in source and binary forms are freely
8 * permitted provided that the above copyright notice and this
9 * paragraph and the following disclaimer are duplicated in all
12 * This software is provided "AS IS" and without any express or
13 * implied warranties, including, without limitation, the implied
14 * warranties of merchantability and fitness for a particular
17 * $DragonFly: src/sys/boot/sparc64/boot1/boot1.c,v 1.2 2006/12/18 20:41:01 dillon Exp $
20 #include <sys/param.h>
21 #include <sys/dirent.h>
22 #include <machine/elf.h>
23 #include <machine/stdarg.h>
25 #define _PATH_LOADER "/boot/loader"
26 #define _PATH_KERNEL "/boot/kernel/kernel"
28 #define BSIZEMAX 16384
30 typedef int putc_func_t(int c
, void *arg
);
31 typedef int32_t ofwh_t
;
39 static const char digits
[] = "0123456789abcdef";
41 static char bootpath
[128];
42 static char bootargs
[128];
44 static ofwh_t bootdev
;
48 static char blkbuf
[BSIZEMAX
];
49 static unsigned int fsblks
;
51 static uint32_t fs_off
;
53 int main(int ac
, char **av
);
55 static void exit(int) __dead2
;
56 static void load(const char *);
57 static int dskread(void *, u_int64_t
, int);
59 static void usage(void);
61 static void bcopy(const void *src
, void *dst
, size_t len
);
62 static void bzero(void *b
, size_t len
);
64 static int mount(const char *device
);
66 static void panic(const char *fmt
, ...) __dead2
;
67 static int printf(const char *fmt
, ...);
68 static int putchar(int c
, void *arg
);
69 static int kvprintf(const char *fmt
, va_list ap
);
70 static int kvsnprintf(char *str
, size_t sz
, const char *fmt
, va_list ap
);
72 static int __printf(const char *fmt
, putc_func_t
*putc
, void *arg
, va_list ap
);
73 static int __putc(int c
, void *arg
);
74 static int __puts(const char *s
, putc_func_t
*putc
, void *arg
);
75 static int __sputc(int c
, void *arg
);
76 static char *__uitoa(char *buf
, u_int val
, int base
);
77 static char *__ultoa(char *buf
, u_long val
, int base
);
80 * Open Firmware interface functions
82 typedef u_int64_t ofwcell_t
;
83 typedef u_int32_t u_ofwh_t
;
84 typedef int (*ofwfp_t
)(ofwcell_t
[]);
85 ofwfp_t ofw
; /* the prom Open Firmware entry */
87 void ofw_init(int, int, int, int, ofwfp_t
);
88 ofwh_t
ofw_finddevice(const char *);
89 ofwh_t
ofw_open(const char *);
90 int ofw_getprop(ofwh_t
, const char *, void *, size_t);
91 int ofw_read(ofwh_t
, void *, size_t);
92 int ofw_write(ofwh_t
, const void *, size_t);
93 int ofw_seek(ofwh_t
, u_int64_t
);
94 void ofw_exit(void) __dead2
;
97 ofwh_t stdinh
, stdouth
;
100 * This has to stay here, as the PROM seems to ignore the
101 * entry point specified in the a.out header. (or elftoaout is broken)
105 ofw_init(int d
, int d1
, int d2
, int d3
, ofwfp_t ofwaddr
)
114 chosenh
= ofw_finddevice("/chosen");
115 ofw_getprop(chosenh
, "stdin", &stdinh
, sizeof(stdinh
));
116 ofw_getprop(chosenh
, "stdout", &stdouth
, sizeof(stdouth
));
117 ofw_getprop(chosenh
, "bootargs", bootargs
, sizeof(bootargs
));
118 ofw_getprop(chosenh
, "bootpath", bootpath
, sizeof(bootpath
));
120 bootargs
[sizeof(bootargs
) - 1] = '\0';
121 bootpath
[sizeof(bootpath
) - 1] = '\0';
126 while (*p
== ' ' && *p
!= '\0')
128 if (*p
== '\0' || ac
>= 16)
131 while (*p
!= ' ' && *p
!= '\0')
141 ofw_finddevice(const char *name
)
144 (ofwcell_t
)"finddevice",
152 printf("ofw_finddevice: name=\"%s\"\n", name
);
159 ofw_getprop(ofwh_t ofwh
, const char *name
, void *buf
, size_t len
)
162 (ofwcell_t
)"getprop",
173 printf("ofw_getprop: ofwh=0x%x buf=%p len=%u\n",
181 ofw_open(const char *path
)
192 printf("ofw_open: path=\"%s\"\n", path
);
199 ofw_close(ofwh_t devh
)
209 printf("ofw_close: devh=0x%x\n", devh
);
216 ofw_read(ofwh_t devh
, void *buf
, size_t len
)
229 printf("ofw_read: devh=0x%x buf=%p len=%u\n", devh
, buf
, len
);
236 ofw_write(ofwh_t devh
, const void *buf
, size_t len
)
249 printf("ofw_write: devh=0x%x buf=%p len=%u\n", devh
, buf
, len
);
256 ofw_seek(ofwh_t devh
, u_int64_t off
)
269 printf("ofw_seek: devh=0x%x off=0x%lx\n", devh
, off
);
280 args
[0] = (ofwcell_t
)"exit";
289 bcopy(const void *src
, void *dst
, size_t len
)
299 memcpy(void *dst
, const void *src
, size_t len
)
301 bcopy(src
, dst
, len
);
305 bzero(void *b
, size_t len
)
314 strcmp(const char *s1
, const char *s2
)
316 for (; *s1
== *s2
&& *s1
; s1
++, s2
++)
318 return ((u_char
)*s1
- (u_char
)*s2
);
324 main(int ac
, char **av
)
330 for (i
= 0; i
< ac
; i
++) {
344 printf(" \n>> FreeBSD/sparc64 boot block\n"
346 " Boot loader: %s\n", bootpath
, path
);
348 if (mount(bootpath
) == -1)
359 printf("usage: boot device [/path/to/loader]\n");
370 static struct dmadat __dmadat
;
373 mount(const char *device
)
377 if ((bootdev
= ofw_open(device
)) == -1) {
378 printf("mount: can't open device\n");
381 if (fsread(0, NULL
, 0)) {
382 printf("mount: can't read superblock\n");
389 load(const char *fname
)
397 if ((ino
= lookup(fname
)) == 0) {
398 printf("File %s not found\n", fname
);
401 if (fsread(ino
, &eh
, sizeof(eh
)) != sizeof(eh
)) {
402 printf("Can't read elf header\n");
406 printf("Not an ELF file\n");
409 for (i
= 0; i
< eh
.e_phnum
; i
++) {
410 fs_off
= eh
.e_phoff
+ i
* eh
.e_phentsize
;
411 if (fsread(ino
, &ph
, sizeof(ph
)) != sizeof(ph
)) {
412 printf("Can't read program header %d\n", i
);
415 if (ph
.p_type
!= PT_LOAD
)
417 fs_off
= ph
.p_offset
;
418 p
= (caddr_t
)ph
.p_vaddr
;
419 if (fsread(ino
, p
, ph
.p_filesz
) != ph
.p_filesz
) {
420 printf("Can't read content of section %d\n", i
);
423 if (ph
.p_filesz
!= ph
.p_memsz
)
424 bzero(p
+ ph
.p_filesz
, ph
.p_memsz
- ph
.p_filesz
);
427 (*(void (*)(int, int, int, int, ofwfp_t
))eh
.e_entry
)(0, 0, 0, 0, ofw
);
431 dskread(void *buf
, u_int64_t lba
, int nblk
)
434 * The OpenFirmware should open the correct partition for us.
435 * That means, if we read from offset zero on an open instance handle,
436 * we should read from offset zero of that partition.
438 ofw_seek(bootdev
, lba
* DEV_BSIZE
);
439 ofw_read(bootdev
, buf
, nblk
* DEV_BSIZE
);
444 panic(const char *fmt
, ...)
450 kvsnprintf(buf
, sizeof buf
, fmt
, ap
);
451 printf("panic: %s\n", buf
);
458 printf(const char *fmt
, ...)
464 ret
= kvprintf(fmt
, ap
);
470 putchar(int c
, void *arg
)
476 ofw_write(stdouth
, &buf
, 1);
479 ofw_write(stdouth
, &buf
, 1);
484 kvprintf(const char *fmt
, va_list ap
)
488 ret
= __printf(fmt
, putchar
, 0, ap
);
493 kvsnprintf(char *str
, size_t sz
, const char *fmt
, va_list ap
)
501 ret
= __printf(fmt
, __sputc
, &sp
, ap
);
506 __printf(const char *fmt
, putc_func_t
*putc
, void *arg
, va_list ap
)
508 char buf
[(sizeof(long) * 8) + 1];
519 nbuf
= &buf
[sizeof buf
- 1];
521 while ((c
= *fmt
++) != 0) {
529 reswitch
: c
= *fmt
++;
535 ret
+= putc('%', arg
);
543 ui
= (u_int
)va_arg(ap
, int);
546 ret
+= putc('-', arg
);
548 s
= __uitoa(nbuf
, ui
, 10);
550 ul
= (u_long
)va_arg(ap
, long);
553 ret
+= putc('-', arg
);
555 s
= __ultoa(nbuf
, ul
, 10);
557 ret
+= __puts(s
, putc
, arg
);
564 ui
= (u_int
)va_arg(ap
, u_int
);
565 s
= __uitoa(nbuf
, ui
, 8);
567 ul
= (u_long
)va_arg(ap
, u_long
);
568 s
= __ultoa(nbuf
, ul
, 8);
570 ret
+= __puts(s
, putc
, arg
);
573 ul
= (u_long
)va_arg(ap
, void *);
574 s
= __ultoa(nbuf
, ul
, 16);
575 ret
+= __puts("0x", putc
, arg
);
576 ret
+= __puts(s
, putc
, arg
);
579 s
= va_arg(ap
, char *);
580 ret
+= __puts(s
, putc
, arg
);
584 ui
= va_arg(ap
, u_int
);
585 s
= __uitoa(nbuf
, ui
, 10);
587 ul
= va_arg(ap
, u_long
);
588 s
= __ultoa(nbuf
, ul
, 10);
590 ret
+= __puts(s
, putc
, arg
);
594 ui
= va_arg(ap
, u_int
);
595 s
= __uitoa(nbuf
, ui
, 16);
597 ul
= va_arg(ap
, u_long
);
598 s
= __ultoa(nbuf
, ul
, 16);
601 ret
+= __puts("0x", putc
, arg
);
602 ret
+= __puts(s
, putc
, arg
);
604 case '0': case '1': case '2': case '3': case '4':
605 case '5': case '6': case '7': case '8': case '9':
606 pad
= pad
* 10 + c
- '0';
616 __sputc(int c
, void *arg
)
621 if (sp
->sp_len
< sp
->sp_size
)
622 sp
->sp_buf
[sp
->sp_len
++] = c
;
623 sp
->sp_buf
[sp
->sp_len
] = '\0';
628 __puts(const char *s
, putc_func_t
*putc
, void *arg
)
634 for (p
= s
; *p
!= '\0'; p
++)
635 ret
+= putc(*p
, arg
);
640 __uitoa(char *buf
, u_int ui
, int base
)
647 *--p
= digits
[ui
% base
];
648 while ((ui
/= base
) != 0);
653 __ultoa(char *buf
, u_long ul
, int base
)
660 *--p
= digits
[ul
% base
];
661 while ((ul
/= base
) != 0);