1ca987d46SWarner Losh /*- 2ca987d46SWarner Losh * Copyright (c) 1998 Robert Nordier 3ca987d46SWarner Losh * All rights reserved. 4ca987d46SWarner Losh * Copyright (c) 2001 Robert Drehmel 5ca987d46SWarner Losh * All rights reserved. 6ca987d46SWarner Losh * 7ca987d46SWarner Losh * Redistribution and use in source and binary forms are freely 8ca987d46SWarner Losh * permitted provided that the above copyright notice and this 9ca987d46SWarner Losh * paragraph and the following disclaimer are duplicated in all 10ca987d46SWarner Losh * such forms. 11ca987d46SWarner Losh * 12ca987d46SWarner Losh * This software is provided "AS IS" and without any express or 13ca987d46SWarner Losh * implied warranties, including, without limitation, the implied 14ca987d46SWarner Losh * warranties of merchantability and fitness for a particular 15ca987d46SWarner Losh * purpose. 16ca987d46SWarner Losh */ 17ca987d46SWarner Losh 18ca987d46SWarner Losh #include <sys/cdefs.h> 19ca987d46SWarner Losh __FBSDID("$FreeBSD$"); 20ca987d46SWarner Losh 21ca987d46SWarner Losh #include <sys/param.h> 22ca987d46SWarner Losh #include <sys/dirent.h> 23ca987d46SWarner Losh #include <machine/elf.h> 24ca987d46SWarner Losh #include <machine/stdarg.h> 25a76b2d3dSWarner Losh #include <machine/md_var.h> 26ca987d46SWarner Losh 27ca987d46SWarner Losh #include "paths.h" 28ca987d46SWarner Losh 29ca987d46SWarner Losh #define BSIZEMAX 16384 30ca987d46SWarner Losh 31ca987d46SWarner Losh typedef int putc_func_t(char c, void *arg); 32ca987d46SWarner Losh typedef int32_t ofwh_t; 33ca987d46SWarner Losh 34ca987d46SWarner Losh struct sp_data { 35ca987d46SWarner Losh char *sp_buf; 36ca987d46SWarner Losh u_int sp_len; 37ca987d46SWarner Losh u_int sp_size; 38ca987d46SWarner Losh }; 39ca987d46SWarner Losh 40ca987d46SWarner Losh static const char digits[] = "0123456789abcdef"; 41ca987d46SWarner Losh 42ca987d46SWarner Losh static char bootpath[128]; 43ca987d46SWarner Losh static char bootargs[128]; 44ca987d46SWarner Losh 45ca987d46SWarner Losh static ofwh_t bootdev; 46ca987d46SWarner Losh 47ca987d46SWarner Losh static struct fs fs; 48ca987d46SWarner Losh static char blkbuf[BSIZEMAX]; 49ca987d46SWarner Losh static unsigned int fsblks; 50ca987d46SWarner Losh 51ca987d46SWarner Losh static uint32_t fs_off; 52ca987d46SWarner Losh 53ca987d46SWarner Losh int main(int ac, char **av); 54ca987d46SWarner Losh 55ca987d46SWarner Losh static void exit(int) __dead2; 56ca987d46SWarner Losh static void load(const char *); 57*56e53cb8SWarner Losh static int dskread(void *, uint64_t, int); 58ca987d46SWarner Losh 59ca987d46SWarner Losh static void usage(void); 60ca987d46SWarner Losh 61ca987d46SWarner Losh static void bcopy(const void *src, void *dst, size_t len); 62ca987d46SWarner Losh static void bzero(void *b, size_t len); 63ca987d46SWarner Losh 64ca987d46SWarner Losh static int domount(const char *device, int quiet); 65ca987d46SWarner Losh 66ca987d46SWarner Losh static void panic(const char *fmt, ...) __dead2; 67ca987d46SWarner Losh static int printf(const char *fmt, ...); 68ca987d46SWarner Losh static int putchar(char c, void *arg); 69ca987d46SWarner Losh static int vprintf(const char *fmt, va_list ap); 70ca987d46SWarner Losh static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap); 71ca987d46SWarner Losh 72ca987d46SWarner Losh static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap); 73ca987d46SWarner Losh static int __putc(char c, void *arg); 74ca987d46SWarner Losh static int __puts(const char *s, putc_func_t *putc, void *arg); 75ca987d46SWarner Losh static int __sputc(char c, void *arg); 76ca987d46SWarner Losh static char *__uitoa(char *buf, u_int val, int base); 77ca987d46SWarner Losh static char *__ultoa(char *buf, u_long val, int base); 78ca987d46SWarner Losh 79ca987d46SWarner Losh /* 80ca987d46SWarner Losh * Open Firmware interface functions 81ca987d46SWarner Losh */ 82*56e53cb8SWarner Losh typedef uint32_t ofwcell_t; 83*56e53cb8SWarner Losh typedef uint32_t u_ofwh_t; 84ca987d46SWarner Losh typedef int (*ofwfp_t)(void *); 85ca987d46SWarner Losh ofwfp_t ofw; /* the prom Open Firmware entry */ 86ca987d46SWarner Losh ofwh_t chosenh; 87ca987d46SWarner Losh 88ca987d46SWarner Losh void ofw_init(void *, int, int (*)(void *), char *, int); 89ca987d46SWarner Losh static ofwh_t ofw_finddevice(const char *); 90ca987d46SWarner Losh static ofwh_t ofw_open(const char *); 91ca987d46SWarner Losh static int ofw_close(ofwh_t); 92ca987d46SWarner Losh static int ofw_getprop(ofwh_t, const char *, void *, size_t); 93ca987d46SWarner Losh static int ofw_setprop(ofwh_t, const char *, void *, size_t); 94ca987d46SWarner Losh static int ofw_read(ofwh_t, void *, size_t); 95ca987d46SWarner Losh static int ofw_write(ofwh_t, const void *, size_t); 96ca987d46SWarner Losh static int ofw_claim(void *virt, size_t len, u_int align); 97*56e53cb8SWarner Losh static int ofw_seek(ofwh_t, uint64_t); 98ca987d46SWarner Losh static void ofw_exit(void) __dead2; 99ca987d46SWarner Losh 100ca987d46SWarner Losh ofwh_t bootdevh; 101ca987d46SWarner Losh ofwh_t stdinh, stdouth; 102ca987d46SWarner Losh 103ca987d46SWarner Losh __asm(" \n\ 104ca987d46SWarner Losh .data \n\ 105ca987d46SWarner Losh .align 4 \n\ 106ca987d46SWarner Losh stack: \n\ 107ca987d46SWarner Losh .space 16384 \n\ 108ca987d46SWarner Losh \n\ 109ca987d46SWarner Losh .text \n\ 110ca987d46SWarner Losh .globl _start \n\ 111ca987d46SWarner Losh _start: \n\ 112ca987d46SWarner Losh lis %r1,stack@ha \n\ 113ca987d46SWarner Losh addi %r1,%r1,stack@l \n\ 114ca987d46SWarner Losh addi %r1,%r1,8192 \n\ 115ca987d46SWarner Losh \n\ 116ca987d46SWarner Losh b ofw_init \n\ 117ca987d46SWarner Losh "); 118ca987d46SWarner Losh 119ca987d46SWarner Losh void 120ca987d46SWarner Losh ofw_init(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl) 121ca987d46SWarner Losh { 122ca987d46SWarner Losh char *av[16]; 123ca987d46SWarner Losh char *p; 124ca987d46SWarner Losh int ac; 125ca987d46SWarner Losh 126ca987d46SWarner Losh ofw = openfirm; 127ca987d46SWarner Losh 128ca987d46SWarner Losh chosenh = ofw_finddevice("/chosen"); 129ca987d46SWarner Losh ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh)); 130ca987d46SWarner Losh ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth)); 131ca987d46SWarner Losh ofw_getprop(chosenh, "bootargs", bootargs, sizeof(bootargs)); 132ca987d46SWarner Losh ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath)); 133ca987d46SWarner Losh 134ca987d46SWarner Losh bootargs[sizeof(bootargs) - 1] = '\0'; 135ca987d46SWarner Losh bootpath[sizeof(bootpath) - 1] = '\0'; 136ca987d46SWarner Losh 137ca987d46SWarner Losh p = bootpath; 138ca987d46SWarner Losh while (*p != '\0') { 139ca987d46SWarner Losh /* Truncate partition ID */ 140ca987d46SWarner Losh if (*p == ':') { 141ca987d46SWarner Losh ofw_close(bootdev); 142ca987d46SWarner Losh *(++p) = '\0'; 143ca987d46SWarner Losh break; 144ca987d46SWarner Losh } 145ca987d46SWarner Losh p++; 146ca987d46SWarner Losh } 147ca987d46SWarner Losh 148ca987d46SWarner Losh ac = 0; 149ca987d46SWarner Losh p = bootargs; 150ca987d46SWarner Losh for (;;) { 151ca987d46SWarner Losh while (*p == ' ' && *p != '\0') 152ca987d46SWarner Losh p++; 153ca987d46SWarner Losh if (*p == '\0' || ac >= 16) 154ca987d46SWarner Losh break; 155ca987d46SWarner Losh av[ac++] = p; 156ca987d46SWarner Losh while (*p != ' ' && *p != '\0') 157ca987d46SWarner Losh p++; 158ca987d46SWarner Losh if (*p != '\0') 159ca987d46SWarner Losh *p++ = '\0'; 160ca987d46SWarner Losh } 161ca987d46SWarner Losh 162ca987d46SWarner Losh exit(main(ac, av)); 163ca987d46SWarner Losh } 164ca987d46SWarner Losh 165ca987d46SWarner Losh static ofwh_t 166ca987d46SWarner Losh ofw_finddevice(const char *name) 167ca987d46SWarner Losh { 168ca987d46SWarner Losh ofwcell_t args[] = { 169ca987d46SWarner Losh (ofwcell_t)"finddevice", 170ca987d46SWarner Losh 1, 171ca987d46SWarner Losh 1, 172ca987d46SWarner Losh (ofwcell_t)name, 173ca987d46SWarner Losh 0 174ca987d46SWarner Losh }; 175ca987d46SWarner Losh 176ca987d46SWarner Losh if ((*ofw)(args)) { 177ca987d46SWarner Losh printf("ofw_finddevice: name=\"%s\"\n", name); 178ca987d46SWarner Losh return (1); 179ca987d46SWarner Losh } 180ca987d46SWarner Losh return (args[4]); 181ca987d46SWarner Losh } 182ca987d46SWarner Losh 183ca987d46SWarner Losh static int 184ca987d46SWarner Losh ofw_getprop(ofwh_t ofwh, const char *name, void *buf, size_t len) 185ca987d46SWarner Losh { 186ca987d46SWarner Losh ofwcell_t args[] = { 187ca987d46SWarner Losh (ofwcell_t)"getprop", 188ca987d46SWarner Losh 4, 189ca987d46SWarner Losh 1, 190ca987d46SWarner Losh (u_ofwh_t)ofwh, 191ca987d46SWarner Losh (ofwcell_t)name, 192ca987d46SWarner Losh (ofwcell_t)buf, 193ca987d46SWarner Losh len, 194ca987d46SWarner Losh 0 195ca987d46SWarner Losh }; 196ca987d46SWarner Losh 197ca987d46SWarner Losh if ((*ofw)(args)) { 198ca987d46SWarner Losh printf("ofw_getprop: ofwh=0x%x buf=%p len=%u\n", 199ca987d46SWarner Losh ofwh, buf, len); 200ca987d46SWarner Losh return (1); 201ca987d46SWarner Losh } 202ca987d46SWarner Losh return (0); 203ca987d46SWarner Losh } 204ca987d46SWarner Losh 205ca987d46SWarner Losh static int 206ca987d46SWarner Losh ofw_setprop(ofwh_t ofwh, const char *name, void *buf, size_t len) 207ca987d46SWarner Losh { 208ca987d46SWarner Losh ofwcell_t args[] = { 209ca987d46SWarner Losh (ofwcell_t)"setprop", 210ca987d46SWarner Losh 4, 211ca987d46SWarner Losh 1, 212ca987d46SWarner Losh (u_ofwh_t)ofwh, 213ca987d46SWarner Losh (ofwcell_t)name, 214ca987d46SWarner Losh (ofwcell_t)buf, 215ca987d46SWarner Losh len, 216ca987d46SWarner Losh 0 217ca987d46SWarner Losh }; 218ca987d46SWarner Losh 219ca987d46SWarner Losh if ((*ofw)(args)) { 220ca987d46SWarner Losh printf("ofw_setprop: ofwh=0x%x buf=%p len=%u\n", 221ca987d46SWarner Losh ofwh, buf, len); 222ca987d46SWarner Losh return (1); 223ca987d46SWarner Losh } 224ca987d46SWarner Losh return (0); 225ca987d46SWarner Losh } 226ca987d46SWarner Losh 227ca987d46SWarner Losh static ofwh_t 228ca987d46SWarner Losh ofw_open(const char *path) 229ca987d46SWarner Losh { 230ca987d46SWarner Losh ofwcell_t args[] = { 231ca987d46SWarner Losh (ofwcell_t)"open", 232ca987d46SWarner Losh 1, 233ca987d46SWarner Losh 1, 234ca987d46SWarner Losh (ofwcell_t)path, 235ca987d46SWarner Losh 0 236ca987d46SWarner Losh }; 237ca987d46SWarner Losh 238ca987d46SWarner Losh if ((*ofw)(args)) { 239ca987d46SWarner Losh printf("ofw_open: path=\"%s\"\n", path); 240ca987d46SWarner Losh return (-1); 241ca987d46SWarner Losh } 242ca987d46SWarner Losh return (args[4]); 243ca987d46SWarner Losh } 244ca987d46SWarner Losh 245ca987d46SWarner Losh static int 246ca987d46SWarner Losh ofw_close(ofwh_t devh) 247ca987d46SWarner Losh { 248ca987d46SWarner Losh ofwcell_t args[] = { 249ca987d46SWarner Losh (ofwcell_t)"close", 250ca987d46SWarner Losh 1, 251ca987d46SWarner Losh 0, 252ca987d46SWarner Losh (u_ofwh_t)devh 253ca987d46SWarner Losh }; 254ca987d46SWarner Losh 255ca987d46SWarner Losh if ((*ofw)(args)) { 256ca987d46SWarner Losh printf("ofw_close: devh=0x%x\n", devh); 257ca987d46SWarner Losh return (1); 258ca987d46SWarner Losh } 259ca987d46SWarner Losh return (0); 260ca987d46SWarner Losh } 261ca987d46SWarner Losh 262ca987d46SWarner Losh static int 263ca987d46SWarner Losh ofw_claim(void *virt, size_t len, u_int align) 264ca987d46SWarner Losh { 265ca987d46SWarner Losh ofwcell_t args[] = { 266ca987d46SWarner Losh (ofwcell_t)"claim", 267ca987d46SWarner Losh 3, 268ca987d46SWarner Losh 1, 269ca987d46SWarner Losh (ofwcell_t)virt, 270ca987d46SWarner Losh len, 271ca987d46SWarner Losh align, 272ca987d46SWarner Losh 0, 273ca987d46SWarner Losh 0 274ca987d46SWarner Losh }; 275ca987d46SWarner Losh 276ca987d46SWarner Losh if ((*ofw)(args)) { 277ca987d46SWarner Losh printf("ofw_claim: virt=%p len=%u\n", virt, len); 278ca987d46SWarner Losh return (1); 279ca987d46SWarner Losh } 280ca987d46SWarner Losh 281ca987d46SWarner Losh return (0); 282ca987d46SWarner Losh } 283ca987d46SWarner Losh 284ca987d46SWarner Losh static int 285ca987d46SWarner Losh ofw_read(ofwh_t devh, void *buf, size_t len) 286ca987d46SWarner Losh { 287ca987d46SWarner Losh ofwcell_t args[] = { 288ca987d46SWarner Losh (ofwcell_t)"read", 289ca987d46SWarner Losh 3, 290ca987d46SWarner Losh 1, 291ca987d46SWarner Losh (u_ofwh_t)devh, 292ca987d46SWarner Losh (ofwcell_t)buf, 293ca987d46SWarner Losh len, 294ca987d46SWarner Losh 0 295ca987d46SWarner Losh }; 296ca987d46SWarner Losh 297ca987d46SWarner Losh if ((*ofw)(args)) { 298ca987d46SWarner Losh printf("ofw_read: devh=0x%x buf=%p len=%u\n", devh, buf, len); 299ca987d46SWarner Losh return (1); 300ca987d46SWarner Losh } 301ca987d46SWarner Losh return (0); 302ca987d46SWarner Losh } 303ca987d46SWarner Losh 304ca987d46SWarner Losh static int 305ca987d46SWarner Losh ofw_write(ofwh_t devh, const void *buf, size_t len) 306ca987d46SWarner Losh { 307ca987d46SWarner Losh ofwcell_t args[] = { 308ca987d46SWarner Losh (ofwcell_t)"write", 309ca987d46SWarner Losh 3, 310ca987d46SWarner Losh 1, 311ca987d46SWarner Losh (u_ofwh_t)devh, 312ca987d46SWarner Losh (ofwcell_t)buf, 313ca987d46SWarner Losh len, 314ca987d46SWarner Losh 0 315ca987d46SWarner Losh }; 316ca987d46SWarner Losh 317ca987d46SWarner Losh if ((*ofw)(args)) { 318ca987d46SWarner Losh printf("ofw_write: devh=0x%x buf=%p len=%u\n", devh, buf, len); 319ca987d46SWarner Losh return (1); 320ca987d46SWarner Losh } 321ca987d46SWarner Losh return (0); 322ca987d46SWarner Losh } 323ca987d46SWarner Losh 324ca987d46SWarner Losh static int 325*56e53cb8SWarner Losh ofw_seek(ofwh_t devh, uint64_t off) 326ca987d46SWarner Losh { 327ca987d46SWarner Losh ofwcell_t args[] = { 328ca987d46SWarner Losh (ofwcell_t)"seek", 329ca987d46SWarner Losh 3, 330ca987d46SWarner Losh 1, 331ca987d46SWarner Losh (u_ofwh_t)devh, 332ca987d46SWarner Losh off >> 32, 333ca987d46SWarner Losh off, 334ca987d46SWarner Losh 0 335ca987d46SWarner Losh }; 336ca987d46SWarner Losh 337ca987d46SWarner Losh if ((*ofw)(args)) { 338ca987d46SWarner Losh printf("ofw_seek: devh=0x%x off=0x%lx\n", devh, off); 339ca987d46SWarner Losh return (1); 340ca987d46SWarner Losh } 341ca987d46SWarner Losh return (0); 342ca987d46SWarner Losh } 343ca987d46SWarner Losh 344ca987d46SWarner Losh static void 345ca987d46SWarner Losh ofw_exit(void) 346ca987d46SWarner Losh { 347ca987d46SWarner Losh ofwcell_t args[3]; 348ca987d46SWarner Losh 349ca987d46SWarner Losh args[0] = (ofwcell_t)"exit"; 350ca987d46SWarner Losh args[1] = 0; 351ca987d46SWarner Losh args[2] = 0; 352ca987d46SWarner Losh 353ca987d46SWarner Losh for (;;) 354ca987d46SWarner Losh (*ofw)(args); 355ca987d46SWarner Losh } 356ca987d46SWarner Losh 357ca987d46SWarner Losh static void 358ca987d46SWarner Losh bcopy(const void *src, void *dst, size_t len) 359ca987d46SWarner Losh { 360ca987d46SWarner Losh const char *s = src; 361ca987d46SWarner Losh char *d = dst; 362ca987d46SWarner Losh 363ca987d46SWarner Losh while (len-- != 0) 364ca987d46SWarner Losh *d++ = *s++; 365ca987d46SWarner Losh } 366ca987d46SWarner Losh 367ca987d46SWarner Losh static void 368ca987d46SWarner Losh memcpy(void *dst, const void *src, size_t len) 369ca987d46SWarner Losh { 370ca987d46SWarner Losh bcopy(src, dst, len); 371ca987d46SWarner Losh } 372ca987d46SWarner Losh 373ca987d46SWarner Losh static void 374ca987d46SWarner Losh bzero(void *b, size_t len) 375ca987d46SWarner Losh { 376ca987d46SWarner Losh char *p = b; 377ca987d46SWarner Losh 378ca987d46SWarner Losh while (len-- != 0) 379ca987d46SWarner Losh *p++ = 0; 380ca987d46SWarner Losh } 381ca987d46SWarner Losh 382ca987d46SWarner Losh static int 383ca987d46SWarner Losh strcmp(const char *s1, const char *s2) 384ca987d46SWarner Losh { 385ca987d46SWarner Losh for (; *s1 == *s2 && *s1; s1++, s2++) 386ca987d46SWarner Losh ; 387ca987d46SWarner Losh return ((u_char)*s1 - (u_char)*s2); 388ca987d46SWarner Losh } 389ca987d46SWarner Losh 390ca987d46SWarner Losh #include "ufsread.c" 391ca987d46SWarner Losh 392ca987d46SWarner Losh int 393ca987d46SWarner Losh main(int ac, char **av) 394ca987d46SWarner Losh { 395ca987d46SWarner Losh const char *path; 396ca987d46SWarner Losh char bootpath_full[255]; 397ca987d46SWarner Losh int i, len; 398ca987d46SWarner Losh 399ca987d46SWarner Losh path = PATH_LOADER; 400ca987d46SWarner Losh for (i = 0; i < ac; i++) { 401ca987d46SWarner Losh switch (av[i][0]) { 402ca987d46SWarner Losh case '-': 403ca987d46SWarner Losh switch (av[i][1]) { 404ca987d46SWarner Losh default: 405ca987d46SWarner Losh usage(); 406ca987d46SWarner Losh } 407ca987d46SWarner Losh break; 408ca987d46SWarner Losh default: 409ca987d46SWarner Losh path = av[i]; 410ca987d46SWarner Losh break; 411ca987d46SWarner Losh } 412ca987d46SWarner Losh } 413ca987d46SWarner Losh 414ca987d46SWarner Losh printf(" \n>> FreeBSD/powerpc Open Firmware boot block\n" 415ca987d46SWarner Losh " Boot path: %s\n" 416ca987d46SWarner Losh " Boot loader: %s\n", bootpath, path); 417ca987d46SWarner Losh 418ca987d46SWarner Losh len = 0; 419ca987d46SWarner Losh while (bootpath[len] != '\0') len++; 420ca987d46SWarner Losh 421ca987d46SWarner Losh memcpy(bootpath_full,bootpath,len+1); 422ca987d46SWarner Losh 423ca987d46SWarner Losh if (bootpath_full[len-1] != ':') { 424ca987d46SWarner Losh /* First try full volume */ 425ca987d46SWarner Losh if (domount(bootpath_full,1) == 0) 426ca987d46SWarner Losh goto out; 427ca987d46SWarner Losh 428ca987d46SWarner Losh /* Add a : so that we try partitions if that fails */ 429ca987d46SWarner Losh if (bootdev > 0) 430ca987d46SWarner Losh ofw_close(bootdev); 431ca987d46SWarner Losh bootpath_full[len] = ':'; 432ca987d46SWarner Losh len += 1; 433ca987d46SWarner Losh } 434ca987d46SWarner Losh 435ca987d46SWarner Losh /* Loop through first 16 partitions to find a UFS one */ 436ca987d46SWarner Losh for (i = 0; i < 16; i++) { 437ca987d46SWarner Losh if (i < 10) { 438ca987d46SWarner Losh bootpath_full[len] = i + '0'; 439ca987d46SWarner Losh bootpath_full[len+1] = '\0'; 440ca987d46SWarner Losh } else { 441ca987d46SWarner Losh bootpath_full[len] = '1'; 442ca987d46SWarner Losh bootpath_full[len+1] = i - 10 + '0'; 443ca987d46SWarner Losh bootpath_full[len+2] = '\0'; 444ca987d46SWarner Losh } 445ca987d46SWarner Losh 446ca987d46SWarner Losh if (domount(bootpath_full,1) >= 0) 447ca987d46SWarner Losh break; 448ca987d46SWarner Losh 449ca987d46SWarner Losh if (bootdev > 0) 450ca987d46SWarner Losh ofw_close(bootdev); 451ca987d46SWarner Losh } 452ca987d46SWarner Losh 453ca987d46SWarner Losh if (i >= 16) 454ca987d46SWarner Losh panic("domount"); 455ca987d46SWarner Losh 456ca987d46SWarner Losh out: 457ca987d46SWarner Losh printf(" Boot volume: %s\n",bootpath_full); 458ca987d46SWarner Losh ofw_setprop(chosenh, "bootargs", bootpath_full, len+2); 459ca987d46SWarner Losh load(path); 460ca987d46SWarner Losh return (1); 461ca987d46SWarner Losh } 462ca987d46SWarner Losh 463ca987d46SWarner Losh static void 464ca987d46SWarner Losh usage(void) 465ca987d46SWarner Losh { 466ca987d46SWarner Losh 467ca987d46SWarner Losh printf("usage: boot device [/path/to/loader]\n"); 468ca987d46SWarner Losh exit(1); 469ca987d46SWarner Losh } 470ca987d46SWarner Losh 471ca987d46SWarner Losh static void 472ca987d46SWarner Losh exit(int code) 473ca987d46SWarner Losh { 474ca987d46SWarner Losh 475ca987d46SWarner Losh ofw_exit(); 476ca987d46SWarner Losh } 477ca987d46SWarner Losh 478ca987d46SWarner Losh static struct dmadat __dmadat; 479ca987d46SWarner Losh 480ca987d46SWarner Losh static int 481ca987d46SWarner Losh domount(const char *device, int quiet) 482ca987d46SWarner Losh { 483ca987d46SWarner Losh 484ca987d46SWarner Losh dmadat = &__dmadat; 485ca987d46SWarner Losh if ((bootdev = ofw_open(device)) == -1) { 486ca987d46SWarner Losh printf("domount: can't open device\n"); 487ca987d46SWarner Losh return (-1); 488ca987d46SWarner Losh } 489ca987d46SWarner Losh if (fsread(0, NULL, 0)) { 490ca987d46SWarner Losh if (!quiet) 491ca987d46SWarner Losh printf("domount: can't read superblock\n"); 492ca987d46SWarner Losh return (-1); 493ca987d46SWarner Losh } 494ca987d46SWarner Losh return (0); 495ca987d46SWarner Losh } 496ca987d46SWarner Losh 497ca987d46SWarner Losh static void 498ca987d46SWarner Losh load(const char *fname) 499ca987d46SWarner Losh { 500ca987d46SWarner Losh Elf32_Ehdr eh; 501ca987d46SWarner Losh Elf32_Phdr ph; 502ca987d46SWarner Losh caddr_t p; 503ca987d46SWarner Losh ufs_ino_t ino; 504ca987d46SWarner Losh int i; 505ca987d46SWarner Losh 506ca987d46SWarner Losh if ((ino = lookup(fname)) == 0) { 507ca987d46SWarner Losh printf("File %s not found\n", fname); 508ca987d46SWarner Losh return; 509ca987d46SWarner Losh } 510ca987d46SWarner Losh if (fsread(ino, &eh, sizeof(eh)) != sizeof(eh)) { 511ca987d46SWarner Losh printf("Can't read elf header\n"); 512ca987d46SWarner Losh return; 513ca987d46SWarner Losh } 514ca987d46SWarner Losh if (!IS_ELF(eh)) { 515ca987d46SWarner Losh printf("Not an ELF file\n"); 516ca987d46SWarner Losh return; 517ca987d46SWarner Losh } 518ca987d46SWarner Losh for (i = 0; i < eh.e_phnum; i++) { 519ca987d46SWarner Losh fs_off = eh.e_phoff + i * eh.e_phentsize; 520ca987d46SWarner Losh if (fsread(ino, &ph, sizeof(ph)) != sizeof(ph)) { 521ca987d46SWarner Losh printf("Can't read program header %d\n", i); 522ca987d46SWarner Losh return; 523ca987d46SWarner Losh } 524ca987d46SWarner Losh if (ph.p_type != PT_LOAD) 525ca987d46SWarner Losh continue; 526ca987d46SWarner Losh fs_off = ph.p_offset; 527ca987d46SWarner Losh p = (caddr_t)ph.p_vaddr; 528ca987d46SWarner Losh ofw_claim(p,(ph.p_filesz > ph.p_memsz) ? 529ca987d46SWarner Losh ph.p_filesz : ph.p_memsz,0); 530ca987d46SWarner Losh if (fsread(ino, p, ph.p_filesz) != ph.p_filesz) { 531ca987d46SWarner Losh printf("Can't read content of section %d\n", i); 532ca987d46SWarner Losh return; 533ca987d46SWarner Losh } 534ca987d46SWarner Losh if (ph.p_filesz != ph.p_memsz) 535ca987d46SWarner Losh bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz); 536ca987d46SWarner Losh __syncicache(p, ph.p_memsz); 537ca987d46SWarner Losh } 538ca987d46SWarner Losh ofw_close(bootdev); 539ca987d46SWarner Losh (*(void (*)(void *, int, ofwfp_t, char *, int))eh.e_entry)(NULL, 0, 540ca987d46SWarner Losh ofw,NULL,0); 541ca987d46SWarner Losh } 542ca987d46SWarner Losh 543ca987d46SWarner Losh static int 544*56e53cb8SWarner Losh dskread(void *buf, uint64_t lba, int nblk) 545ca987d46SWarner Losh { 546ca987d46SWarner Losh /* 547ca987d46SWarner Losh * The Open Firmware should open the correct partition for us. 548ca987d46SWarner Losh * That means, if we read from offset zero on an open instance handle, 549ca987d46SWarner Losh * we should read from offset zero of that partition. 550ca987d46SWarner Losh */ 551ca987d46SWarner Losh ofw_seek(bootdev, lba * DEV_BSIZE); 552ca987d46SWarner Losh ofw_read(bootdev, buf, nblk * DEV_BSIZE); 553ca987d46SWarner Losh return (0); 554ca987d46SWarner Losh } 555ca987d46SWarner Losh 556ca987d46SWarner Losh static void 557ca987d46SWarner Losh panic(const char *fmt, ...) 558ca987d46SWarner Losh { 559ca987d46SWarner Losh char buf[128]; 560ca987d46SWarner Losh va_list ap; 561ca987d46SWarner Losh 562ca987d46SWarner Losh va_start(ap, fmt); 563ca987d46SWarner Losh vsnprintf(buf, sizeof buf, fmt, ap); 564ca987d46SWarner Losh printf("panic: %s\n", buf); 565ca987d46SWarner Losh va_end(ap); 566ca987d46SWarner Losh 567ca987d46SWarner Losh exit(1); 568ca987d46SWarner Losh } 569ca987d46SWarner Losh 570ca987d46SWarner Losh static int 571ca987d46SWarner Losh printf(const char *fmt, ...) 572ca987d46SWarner Losh { 573ca987d46SWarner Losh va_list ap; 574ca987d46SWarner Losh int ret; 575ca987d46SWarner Losh 576ca987d46SWarner Losh va_start(ap, fmt); 577ca987d46SWarner Losh ret = vprintf(fmt, ap); 578ca987d46SWarner Losh va_end(ap); 579ca987d46SWarner Losh return (ret); 580ca987d46SWarner Losh } 581ca987d46SWarner Losh 582ca987d46SWarner Losh static int 583ca987d46SWarner Losh putchar(char c, void *arg) 584ca987d46SWarner Losh { 585ca987d46SWarner Losh char buf; 586ca987d46SWarner Losh 587ca987d46SWarner Losh if (c == '\n') { 588ca987d46SWarner Losh buf = '\r'; 589ca987d46SWarner Losh ofw_write(stdouth, &buf, 1); 590ca987d46SWarner Losh } 591ca987d46SWarner Losh buf = c; 592ca987d46SWarner Losh ofw_write(stdouth, &buf, 1); 593ca987d46SWarner Losh return (1); 594ca987d46SWarner Losh } 595ca987d46SWarner Losh 596ca987d46SWarner Losh static int 597ca987d46SWarner Losh vprintf(const char *fmt, va_list ap) 598ca987d46SWarner Losh { 599ca987d46SWarner Losh int ret; 600ca987d46SWarner Losh 601ca987d46SWarner Losh ret = __printf(fmt, putchar, 0, ap); 602ca987d46SWarner Losh return (ret); 603ca987d46SWarner Losh } 604ca987d46SWarner Losh 605ca987d46SWarner Losh static int 606ca987d46SWarner Losh vsnprintf(char *str, size_t sz, const char *fmt, va_list ap) 607ca987d46SWarner Losh { 608ca987d46SWarner Losh struct sp_data sp; 609ca987d46SWarner Losh int ret; 610ca987d46SWarner Losh 611ca987d46SWarner Losh sp.sp_buf = str; 612ca987d46SWarner Losh sp.sp_len = 0; 613ca987d46SWarner Losh sp.sp_size = sz; 614ca987d46SWarner Losh ret = __printf(fmt, __sputc, &sp, ap); 615ca987d46SWarner Losh return (ret); 616ca987d46SWarner Losh } 617ca987d46SWarner Losh 618ca987d46SWarner Losh static int 619ca987d46SWarner Losh __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap) 620ca987d46SWarner Losh { 621ca987d46SWarner Losh char buf[(sizeof(long) * 8) + 1]; 622ca987d46SWarner Losh char *nbuf; 623ca987d46SWarner Losh u_long ul; 624ca987d46SWarner Losh u_int ui; 625ca987d46SWarner Losh int lflag; 626ca987d46SWarner Losh int sflag; 627ca987d46SWarner Losh char *s; 628ca987d46SWarner Losh int pad; 629ca987d46SWarner Losh int ret; 630ca987d46SWarner Losh int c; 631ca987d46SWarner Losh 632ca987d46SWarner Losh nbuf = &buf[sizeof buf - 1]; 633ca987d46SWarner Losh ret = 0; 634ca987d46SWarner Losh while ((c = *fmt++) != 0) { 635ca987d46SWarner Losh if (c != '%') { 636ca987d46SWarner Losh ret += putc(c, arg); 637ca987d46SWarner Losh continue; 638ca987d46SWarner Losh } 639ca987d46SWarner Losh lflag = 0; 640ca987d46SWarner Losh sflag = 0; 641ca987d46SWarner Losh pad = 0; 642ca987d46SWarner Losh reswitch: c = *fmt++; 643ca987d46SWarner Losh switch (c) { 644ca987d46SWarner Losh case '#': 645ca987d46SWarner Losh sflag = 1; 646ca987d46SWarner Losh goto reswitch; 647ca987d46SWarner Losh case '%': 648ca987d46SWarner Losh ret += putc('%', arg); 649ca987d46SWarner Losh break; 650ca987d46SWarner Losh case 'c': 651ca987d46SWarner Losh c = va_arg(ap, int); 652ca987d46SWarner Losh ret += putc(c, arg); 653ca987d46SWarner Losh break; 654ca987d46SWarner Losh case 'd': 655ca987d46SWarner Losh if (lflag == 0) { 656ca987d46SWarner Losh ui = (u_int)va_arg(ap, int); 657ca987d46SWarner Losh if (ui < (int)ui) { 658ca987d46SWarner Losh ui = -ui; 659ca987d46SWarner Losh ret += putc('-', arg); 660ca987d46SWarner Losh } 661ca987d46SWarner Losh s = __uitoa(nbuf, ui, 10); 662ca987d46SWarner Losh } else { 663ca987d46SWarner Losh ul = (u_long)va_arg(ap, long); 664ca987d46SWarner Losh if (ul < (long)ul) { 665ca987d46SWarner Losh ul = -ul; 666ca987d46SWarner Losh ret += putc('-', arg); 667ca987d46SWarner Losh } 668ca987d46SWarner Losh s = __ultoa(nbuf, ul, 10); 669ca987d46SWarner Losh } 670ca987d46SWarner Losh ret += __puts(s, putc, arg); 671ca987d46SWarner Losh break; 672ca987d46SWarner Losh case 'l': 673ca987d46SWarner Losh lflag = 1; 674ca987d46SWarner Losh goto reswitch; 675ca987d46SWarner Losh case 'o': 676ca987d46SWarner Losh if (lflag == 0) { 677ca987d46SWarner Losh ui = (u_int)va_arg(ap, u_int); 678ca987d46SWarner Losh s = __uitoa(nbuf, ui, 8); 679ca987d46SWarner Losh } else { 680ca987d46SWarner Losh ul = (u_long)va_arg(ap, u_long); 681ca987d46SWarner Losh s = __ultoa(nbuf, ul, 8); 682ca987d46SWarner Losh } 683ca987d46SWarner Losh ret += __puts(s, putc, arg); 684ca987d46SWarner Losh break; 685ca987d46SWarner Losh case 'p': 686ca987d46SWarner Losh ul = (u_long)va_arg(ap, void *); 687ca987d46SWarner Losh s = __ultoa(nbuf, ul, 16); 688ca987d46SWarner Losh ret += __puts("0x", putc, arg); 689ca987d46SWarner Losh ret += __puts(s, putc, arg); 690ca987d46SWarner Losh break; 691ca987d46SWarner Losh case 's': 692ca987d46SWarner Losh s = va_arg(ap, char *); 693ca987d46SWarner Losh ret += __puts(s, putc, arg); 694ca987d46SWarner Losh break; 695ca987d46SWarner Losh case 'u': 696ca987d46SWarner Losh if (lflag == 0) { 697ca987d46SWarner Losh ui = va_arg(ap, u_int); 698ca987d46SWarner Losh s = __uitoa(nbuf, ui, 10); 699ca987d46SWarner Losh } else { 700ca987d46SWarner Losh ul = va_arg(ap, u_long); 701ca987d46SWarner Losh s = __ultoa(nbuf, ul, 10); 702ca987d46SWarner Losh } 703ca987d46SWarner Losh ret += __puts(s, putc, arg); 704ca987d46SWarner Losh break; 705ca987d46SWarner Losh case 'x': 706ca987d46SWarner Losh if (lflag == 0) { 707ca987d46SWarner Losh ui = va_arg(ap, u_int); 708ca987d46SWarner Losh s = __uitoa(nbuf, ui, 16); 709ca987d46SWarner Losh } else { 710ca987d46SWarner Losh ul = va_arg(ap, u_long); 711ca987d46SWarner Losh s = __ultoa(nbuf, ul, 16); 712ca987d46SWarner Losh } 713ca987d46SWarner Losh if (sflag) 714ca987d46SWarner Losh ret += __puts("0x", putc, arg); 715ca987d46SWarner Losh ret += __puts(s, putc, arg); 716ca987d46SWarner Losh break; 717ca987d46SWarner Losh case '0': case '1': case '2': case '3': case '4': 718ca987d46SWarner Losh case '5': case '6': case '7': case '8': case '9': 719ca987d46SWarner Losh pad = pad * 10 + c - '0'; 720ca987d46SWarner Losh goto reswitch; 721ca987d46SWarner Losh default: 722ca987d46SWarner Losh break; 723ca987d46SWarner Losh } 724ca987d46SWarner Losh } 725ca987d46SWarner Losh return (ret); 726ca987d46SWarner Losh } 727ca987d46SWarner Losh 728ca987d46SWarner Losh static int 729ca987d46SWarner Losh __sputc(char c, void *arg) 730ca987d46SWarner Losh { 731ca987d46SWarner Losh struct sp_data *sp; 732ca987d46SWarner Losh 733ca987d46SWarner Losh sp = arg; 734ca987d46SWarner Losh if (sp->sp_len < sp->sp_size) 735ca987d46SWarner Losh sp->sp_buf[sp->sp_len++] = c; 736ca987d46SWarner Losh sp->sp_buf[sp->sp_len] = '\0'; 737ca987d46SWarner Losh return (1); 738ca987d46SWarner Losh } 739ca987d46SWarner Losh 740ca987d46SWarner Losh static int 741ca987d46SWarner Losh __puts(const char *s, putc_func_t *putc, void *arg) 742ca987d46SWarner Losh { 743ca987d46SWarner Losh const char *p; 744ca987d46SWarner Losh int ret; 745ca987d46SWarner Losh 746ca987d46SWarner Losh ret = 0; 747ca987d46SWarner Losh for (p = s; *p != '\0'; p++) 748ca987d46SWarner Losh ret += putc(*p, arg); 749ca987d46SWarner Losh return (ret); 750ca987d46SWarner Losh } 751ca987d46SWarner Losh 752ca987d46SWarner Losh static char * 753ca987d46SWarner Losh __uitoa(char *buf, u_int ui, int base) 754ca987d46SWarner Losh { 755ca987d46SWarner Losh char *p; 756ca987d46SWarner Losh 757ca987d46SWarner Losh p = buf; 758ca987d46SWarner Losh *p = '\0'; 759ca987d46SWarner Losh do 760ca987d46SWarner Losh *--p = digits[ui % base]; 761ca987d46SWarner Losh while ((ui /= base) != 0); 762ca987d46SWarner Losh return (p); 763ca987d46SWarner Losh } 764ca987d46SWarner Losh 765ca987d46SWarner Losh static char * 766ca987d46SWarner Losh __ultoa(char *buf, u_long ul, int base) 767ca987d46SWarner Losh { 768ca987d46SWarner Losh char *p; 769ca987d46SWarner Losh 770ca987d46SWarner Losh p = buf; 771ca987d46SWarner Losh *p = '\0'; 772ca987d46SWarner Losh do 773ca987d46SWarner Losh *--p = digits[ul % base]; 774ca987d46SWarner Losh while ((ul /= base) != 0); 775ca987d46SWarner Losh return (p); 776ca987d46SWarner Losh } 777