boot1.c revision 91678
190699Srobert/* 290699Srobert * Copyright (c) 1998 Robert Nordier 390699Srobert * All rights reserved. 490699Srobert * Copyright (c) 2001 Robert Drehmel 590699Srobert * All rights reserved. 690699Srobert * 790699Srobert * Redistribution and use in source and binary forms are freely 890699Srobert * permitted provided that the above copyright notice and this 990699Srobert * paragraph and the following disclaimer are duplicated in all 1090699Srobert * such forms. 1190699Srobert * 1290699Srobert * This software is provided "AS IS" and without any express or 1390699Srobert * implied warranties, including, without limitation, the implied 1490699Srobert * warranties of merchantability and fitness for a particular 1590699Srobert * purpose. 1690699Srobert * 1790699Srobert */ 1891295Srobert 1991295Srobert#include <sys/cdefs.h> 2091295Srobert__FBSDID("$FreeBSD: head/sys/boot/sparc64/boot1/boot1.c 91678 2002-03-05 11:22:43Z robert $"); 2191295Srobert 2290699Srobert#include <sys/param.h> 2390699Srobert#include <sys/reboot.h> 2490699Srobert#include <sys/diskslice.h> 2590699Srobert#include <sys/disklabel.h> 2690699Srobert#include <sys/dirent.h> 2790699Srobert#include <machine/elf.h> 2890699Srobert#include <machine/stdarg.h> 2990699Srobert 3090699Srobert#include <ufs/ffs/fs.h> 3190699Srobert#include <ufs/ufs/dinode.h> 3290699Srobert 3390699Srobert#include <a.out.h> 3490699Srobert 3590699Srobert#define RBX_ASKNAME 0x0 /* -a */ 3690699Srobert#define RBX_SINGLE 0x1 /* -s */ 3790699Srobert#define RBX_DFLTROOT 0x5 /* -r */ 3890699Srobert#define RBX_KDB 0x6 /* -d */ 3990699Srobert#define RBX_CONFIG 0xa /* -c */ 4090699Srobert#define RBX_VERBOSE 0xb /* -v */ 4190699Srobert#define RBX_CDROM 0xd /* -C */ 4290699Srobert#define RBX_GDB 0xf /* -g */ 4390699Srobert 4490699Srobert#define RBX_MASK 0x2000ffff 4590699Srobert 4690699Srobert#define PATH_CONFIG "/boot.config" 4790699Srobert#define PATH_LOADER "/boot/loader" 4890699Srobert#define PATH_KERNEL "/kernel" 4990699Srobert 5090699Srobert#define ARGS 0x900 5190699Srobert#define NOPT 11 5290699Srobert#define BSIZEMAX 8192 5390699Srobert#define NDEV 5 5490699Srobert 5590699Srobert#define TYPE_AD 0 5690699Srobert#define TYPE_WD 1 5790699Srobert#define TYPE_WFD 2 5890699Srobert#define TYPE_FD 3 5990699Srobert#define TYPE_DA 4 6090699Srobert 6190699Srobert/* 6290699Srobert * This structure will be refined along with the addition of a bootpath 6390699Srobert * parsing routine when it is necessary to cope with bootpaths that are 6490699Srobert * not in the exact <devpath>@<controller>,<disk>:<partition> format and 6590699Srobert * for which we need to evaluate the disklabel ourselves. 6690699Srobert */ 6790699Srobertstruct disk { 6890699Srobert int meta; 6990699Srobert}; 7090699Srobertstruct disk dsk; 7190699Srobert 7290699Srobertextern uint32_t _end; 7390699Srobert 7490699Srobertstatic const char optstr[NOPT] = "aCcgrsv"; 7590699Srobertstatic const unsigned char flags[NOPT] = { 7691295Srobert RBX_ASKNAME, 7791295Srobert RBX_CDROM, 7891295Srobert RBX_CONFIG, 7991295Srobert RBX_GDB, 8091295Srobert RBX_DFLTROOT, 8191295Srobert RBX_SINGLE, 8291295Srobert RBX_VERBOSE 8390699Srobert}; 8490699Srobert 8590699Srobertstatic char cmd[512]; /* command to parse */ 8690699Srobertstatic char bname[1024]; /* name of the binary to load */ 8790699Srobertstatic uint32_t opts; 8890699Srobertstatic int ls; 8990699Srobertstatic uint32_t fs_off; 9090699Srobert 9190699Srobertint main(void); 9290699Srobertvoid exit(int); 9390699Srobertstatic void load(const char *); 9490699Srobertstatic int parse(char *); 9590699Srobertstatic ino_t lookup(const char *); 9690699Srobertstatic int xfsread(ino_t, void *, size_t); 9790699Srobertstatic ssize_t fsread(ino_t, void *, size_t); 9890699Srobertstatic int dskread(void *, u_int64_t, int); 9990699Srobertstatic int printf(const char *, ...); 10090699Srobertstatic int putchar(int); 10190699Srobertstatic int keyhit(unsigned int); 10290699Srobertstatic int getc(void); 10390699Srobert 10490699Srobertstatic void *memcpy(void *, const void *, size_t); 10590699Srobertstatic void *memset(void *, int, size_t); 10690699Srobertstatic void *malloc(size_t); 10790699Srobert 10890699Srobert/* 10990699Srobert * Open Firmware interface functions 11090699Srobert */ 11190699Sroberttypedef u_int64_t ofwcell_t; 11290699Sroberttypedef int32_t ofwh_t; 11390699Sroberttypedef u_int32_t u_ofwh_t; 11490699Sroberttypedef int (*ofwfp_t)(ofwcell_t []); 11590699Srobertofwfp_t ofw; /* the prom Open Firmware entry */ 11690699Srobert 11790699Srobertvoid ofw_init(int, int, int, int, ofwfp_t); 11890699Srobertofwh_t ofw_finddevice(const char *); 11990699Srobertofwh_t ofw_open(const char *); 12090699Srobertint ofw_getprop(ofwh_t, const char *, void *, size_t); 12190699Srobertint ofw_read(ofwh_t, void *, size_t); 12290699Srobertint ofw_write(ofwh_t, const void *, size_t); 12390699Srobertint ofw_seek(ofwh_t, u_int64_t); 12490699Srobert 12590699Srobertofwh_t bootdevh; 12690699Srobertofwh_t stdinh, stdouth; 12790699Srobertchar bootpath[64]; 12890699Srobert 12990699Srobert/* 13090699Srobert * This has to stay here, as the PROM seems to ignore the 13190699Srobert * entry point specified in the a.out header. (or elftoaout is broken) 13290699Srobert */ 13390699Srobert 13490699Srobertvoid 13590699Srobertofw_init(int d, int d1, int d2, int d3, ofwfp_t ofwaddr) 13690699Srobert{ 13790699Srobert ofwh_t chosenh; 13890699Srobert 13990699Srobert ofw = ofwaddr; 14090699Srobert 14190699Srobert chosenh = ofw_finddevice("/chosen"); 14290699Srobert ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh)); 14390699Srobert ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth)); 14490699Srobert ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath)); 14590699Srobert 14690699Srobert if ((bootdevh = ofw_open(bootpath)) == -1) { 14790699Srobert printf("Could not open boot device.\n"); 14890699Srobert } 14990699Srobert 15090699Srobert main(); 15190699Srobert d = d1 = d2 = d3; /* make GCC happy */ 15290699Srobert} 15390699Srobert 15490699Srobertofwh_t 15590699Srobertofw_finddevice(const char *name) 15690699Srobert{ 15791295Srobert ofwcell_t args[] = { 15891295Srobert (ofwcell_t)"finddevice", 15991295Srobert 1, 16091295Srobert 1, 16191295Srobert (ofwcell_t)name, 16291295Srobert 0 16391295Srobert }; 16491295Srobert 16591295Srobert if ((*ofw)(args)) { 16691295Srobert printf("ofw_finddevice: name=\"%s\"\n", name); 16791295Srobert return (1); 16891295Srobert } 16991295Srobert return (args[4]); 17090699Srobert} 17190699Srobert 17290699Srobertint 17390699Srobertofw_getprop(ofwh_t ofwh, const char *name, void *buf, size_t len) 17490699Srobert{ 17591295Srobert ofwcell_t args[] = { 17691295Srobert (ofwcell_t)"getprop", 17791295Srobert 4, 17891295Srobert 1, 17991295Srobert (u_ofwh_t)ofwh, 18091295Srobert (ofwcell_t)name, 18191295Srobert (ofwcell_t)buf, 18291295Srobert len, 18390699Srobert 0 18491295Srobert }; 18591295Srobert 18691295Srobert if ((*ofw)(args)) { 18791295Srobert printf("ofw_getprop: ofwh=0x%x buf=%p len=%u\n", 18891295Srobert ofwh, buf, len); 18991295Srobert return (1); 19091295Srobert } 19191295Srobert return (0); 19290699Srobert} 19390699Srobert 19490699Srobertofwh_t 19590699Srobertofw_open(const char *path) 19690699Srobert{ 19791295Srobert ofwcell_t args[] = { 19891295Srobert (ofwcell_t)"open", 19991295Srobert 1, 20091295Srobert 1, 20191295Srobert (ofwcell_t)path, 20291295Srobert 0 20391295Srobert }; 20491295Srobert 20591295Srobert if ((*ofw)(args)) { 20691295Srobert printf("ofw_open: path=\"%s\"\n", path); 20791295Srobert return (-1); 20891295Srobert } 20991295Srobert return (args[4]); 21090699Srobert} 21190699Srobert 21290699Srobertint 21390699Srobertofw_close(ofwh_t devh) 21490699Srobert{ 21591295Srobert ofwcell_t args[] = { 21691295Srobert (ofwcell_t)"close", 21791295Srobert 1, 21891295Srobert 0, 21991295Srobert (u_ofwh_t)devh 22091295Srobert }; 22191295Srobert 22291295Srobert if ((*ofw)(args)) { 22391295Srobert printf("ofw_close: devh=0x%x\n", devh); 22491295Srobert return (1); 22591295Srobert } 22691295Srobert return (0); 22790699Srobert} 22890699Srobert 22990699Srobertint 23090699Srobertofw_read(ofwh_t devh, void *buf, size_t len) 23190699Srobert{ 23291295Srobert ofwcell_t args[] = { 23391295Srobert (ofwcell_t)"read", 23491295Srobert 4, 23591295Srobert 1, 23691295Srobert (u_ofwh_t)devh, 23791295Srobert (ofwcell_t)buf, 23891295Srobert len, 23991295Srobert 0 24091295Srobert }; 24191295Srobert 24291295Srobert if ((*ofw)(args)) { 24391295Srobert printf("ofw_read: devh=0x%x buf=%p len=%u\n", devh, buf, len); 24491295Srobert return (1); 24591295Srobert } 24691295Srobert return (0); 24790699Srobert} 24890699Srobert 24990699Srobertint 25090699Srobertofw_write(ofwh_t devh, const void *buf, size_t len) 25190699Srobert{ 25291295Srobert ofwcell_t args[] = { 25391295Srobert (ofwcell_t)"write", 25491295Srobert 3, 25591295Srobert 1, 25691295Srobert (u_ofwh_t)devh, 25791295Srobert (ofwcell_t)buf, 25891295Srobert len, 25991295Srobert 0 26091295Srobert }; 26191295Srobert 26291295Srobert if ((*ofw)(args)) { 26391295Srobert printf("ofw_write: devh=0x%x buf=%p len=%u\n", devh, buf, len); 26491295Srobert return (1); 26591295Srobert } 26691295Srobert return (0); 26790699Srobert} 26890699Srobert 26990699Srobertint 27090699Srobertofw_seek(ofwh_t devh, u_int64_t off) 27190699Srobert{ 27291295Srobert ofwcell_t args[] = { 27391295Srobert (ofwcell_t)"seek", 27491295Srobert 4, 27591295Srobert 1, 27691295Srobert (u_ofwh_t)devh, 27791295Srobert off >> 32, 27891678Srobert off, 27991295Srobert 0 28091295Srobert }; 28191295Srobert 28291295Srobert if ((*ofw)(args)) { 28391295Srobert printf("ofw_seek: devh=0x%x off=0x%lx\n", devh, off); 28491295Srobert return (1); 28591295Srobert } 28691295Srobert return (0); 28790699Srobert} 28890699Srobert 28990699Srobertstatic void 29090699Srobertreadfile(const char *fname, void *buf, size_t size) 29190699Srobert{ 29291295Srobert ino_t ino; 29390699Srobert 29491295Srobert if ((ino = lookup(fname))) 29591295Srobert fsread(ino, buf, size); 29690699Srobert} 29790699Srobert 29890699Srobertstatic int 29990699Srobertstrcmp(const char *s1, const char *s2) 30090699Srobert{ 30191295Srobert for (; *s1 == *s2 && *s1; s1++, s2++) 30291295Srobert ; 30391295Srobert return ((u_char)*s1 - (u_char)*s2); 30490699Srobert} 30590699Srobert 30690699Srobertstatic void * 30790699Srobertmemset(void *dst, int val, size_t len) 30890699Srobert{ 30991295Srobert void *ret; 31091295Srobert 31191295Srobert ret = dst; 31290699Srobert while (len) { 31390699Srobert *((char *)dst)++ = val; 31490699Srobert len--; 31590699Srobert } 31691295Srobert return (ret); 31790699Srobert} 31890699Srobert 31990699Srobertstatic int 32090699Srobertfsfind(const char *name, ino_t * ino) 32190699Srobert{ 32291295Srobert char buf[DEV_BSIZE]; 32391295Srobert struct dirent *d; 32491295Srobert char *s; 32591295Srobert ssize_t n; 32690699Srobert 32791295Srobert fs_off = 0; 32891295Srobert while ((n = fsread(*ino, buf, DEV_BSIZE)) > 0) { 32991295Srobert for (s = buf; s < buf + DEV_BSIZE;) { 33091295Srobert d = (void *)s; 33191295Srobert if (ls) 33291295Srobert printf("%s ", d->d_name); 33391295Srobert else if (!strcmp(name, d->d_name)) { 33491295Srobert *ino = d->d_fileno; 33591295Srobert return (d->d_type); 33691295Srobert } 33791295Srobert s += d->d_reclen; 33891295Srobert } 33990699Srobert } 34091295Srobert if (n != -1 && ls) 34191295Srobert putchar('\n'); 34291295Srobert return (0); 34390699Srobert} 34490699Srobert 34590699Srobertstatic int 34690699Srobertgetchar(void) 34790699Srobert{ 34891295Srobert int c; 34990699Srobert 35091295Srobert c = getc(); 35191295Srobert if (c == '\r') 35291295Srobert c = '\n'; 35391295Srobert return (c); 35490699Srobert} 35590699Srobert 35690699Srobertstatic void 35790699Srobertgetstr(char *str, int size) 35890699Srobert{ 35991295Srobert char *s; 36091295Srobert int c; 36190699Srobert 36291295Srobert s = str; 36391295Srobert do { 36491295Srobert switch (c = getchar()) { 36591295Srobert case 0: 36691295Srobert break; 36791295Srobert case '\b': 36891295Srobert case '\177': 36991295Srobert if (s > str) { 37091295Srobert s--; 37191295Srobert putchar('\b'); 37291295Srobert putchar(' '); 37391295Srobert } else 37491295Srobert c = 0; 37591295Srobert break; 37691295Srobert case '\n': 37791295Srobert *s = 0; 37891295Srobert break; 37991295Srobert default: 38091295Srobert if (s - str < size - 1) 38191295Srobert *s++ = c; 38291295Srobert } 38391295Srobert if (c) 38491295Srobert putchar(c); 38591295Srobert } while (c != '\n'); 38690699Srobert} 38790699Srobert 38890699Srobertstatic void 38990699Srobertputc(int c) 39090699Srobert{ 39191295Srobert char d; 39291295Srobert 39391295Srobert d = c; 39490699Srobert ofw_write(stdouth, &d, 1); 39590699Srobert} 39690699Srobert 39790699Srobertint main(void) 39890699Srobert{ 39991295Srobert readfile(PATH_CONFIG, cmd, sizeof(cmd)); 40091295Srobert if (cmd[0] != '\0') { 40191295Srobert printf("%s: %s", PATH_CONFIG, cmd); 40291295Srobert if (parse(cmd)) 40391295Srobert cmd[0] = '\0'; 40491295Srobert } 40591295Srobert if (bname[0] == '\0') 40691295Srobert memcpy(bname, PATH_LOADER, sizeof(PATH_LOADER)); 40790699Srobert 40891295Srobert printf(" \n>> FreeBSD/sparc64 boot block\n" 40990699Srobert " Boot path: %s\n" 41090699Srobert " Boot loader: %s\n", bootpath, PATH_LOADER); 41191295Srobert load(bname); 41291295Srobert return (1); 41390699Srobert} 41490699Srobert 41590699Srobertstatic void 41690699Srobertload(const char *fname) 41790699Srobert{ 41891295Srobert Elf64_Ehdr eh; 41991295Srobert Elf64_Phdr ep[2]; 42091295Srobert Elf64_Shdr es[2]; 42191295Srobert caddr_t p; 42291295Srobert ino_t ino; 42391295Srobert vm_offset_t entry; 42491295Srobert int i, j; 42590699Srobert 42691295Srobert if ((ino = lookup(fname)) == 0) { 42791295Srobert if (!ls) 42891295Srobert printf("File %s not found\n", fname); 42990699Srobert return; 43090699Srobert } 43191295Srobert if (xfsread(ino, &eh, sizeof(eh))) 43291295Srobert return; 43391295Srobert if (!IS_ELF(eh)) { 43491295Srobert printf("Not an ELF file\n"); 43591295Srobert return; 43691295Srobert } 43791295Srobert fs_off = eh.e_phoff; 43891295Srobert for (j = i = 0; i < eh.e_phnum && j < 2; i++) { 43991295Srobert if (xfsread(ino, ep + j, sizeof(ep[0]))) 44091295Srobert return; 44191295Srobert if (ep[j].p_type == PT_LOAD) 44291295Srobert j++; 44391295Srobert } 44491295Srobert for (i = 0; i < j; i++) { 44591295Srobert p = (caddr_t)ep[i].p_vaddr; 44691295Srobert fs_off = ep[i].p_offset; 44791295Srobert if (xfsread(ino, p, ep[i].p_filesz)) 44891295Srobert return; 44991295Srobert /* 45091295Srobert * Assume the second program header table entry 45191295Srobert * to contain data and bss. Clear out the .bss section. 45291295Srobert */ 45391295Srobert if (i == 1) { 45491295Srobert memset(p + ep[i].p_filesz, 0, 45591295Srobert ep[i].p_memsz - ep[i].p_filesz); 45691295Srobert } 45791295Srobert } 45891295Srobert p += roundup2(ep[1].p_memsz, PAGE_SIZE); 45991295Srobert if (eh.e_shnum == eh.e_shstrndx + 3) { 46091295Srobert fs_off = eh.e_shoff + sizeof(es[0]) * (eh.e_shstrndx + 1); 46191295Srobert if (xfsread(ino, &es, sizeof(es))) 46291295Srobert return; 46391295Srobert for (i = 0; i < 2; i++) { 46491295Srobert memcpy(p, &es[i].sh_size, sizeof(es[i].sh_size)); 46591295Srobert p += sizeof(es[i].sh_size); 46691295Srobert fs_off = es[i].sh_offset; 46791295Srobert if (xfsread(ino, p, es[i].sh_size)) 46891295Srobert return; 46991295Srobert p += es[i].sh_size; 47091295Srobert } 47191295Srobert } 47291295Srobert entry = eh.e_entry; 47391295Srobert ofw_close(bootdevh); 47491295Srobert (*(void (*)(int, int, int, int, ofwfp_t))entry)(0, 0, 0, 0, ofw); 47590699Srobert} 47690699Srobert 47790699Srobertstatic int 47890699Srobertparse(char *arg) 47990699Srobert{ 48091295Srobert char *p; 48191295Srobert int c, i; 48290699Srobert 48391295Srobert while ((c = *arg++)) { 48491295Srobert if (c == ' ' || c == '\t' || c == '\n') 48591295Srobert continue; 48691295Srobert for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++) 48791295Srobert ; 48891295Srobert if (*p) 48991295Srobert *p++ = 0; 49091295Srobert if (c == '-') { 49191295Srobert while ((c = *arg++)) { 49291295Srobert for (i = 0; c != optstr[i]; i++) 49391295Srobert if (i == NOPT - 1) 49491295Srobert return (-1); 49591295Srobert opts ^= 1 << flags[i]; 49691295Srobert } 49791295Srobert } 49891295Srobert arg = p; 49990699Srobert } 50091295Srobert return (0); 50190699Srobert} 50290699Srobert 50390699Srobertstatic ino_t 50490699Srobertlookup(const char *path) 50590699Srobert{ 50691295Srobert char name[MAXNAMLEN + 1]; 50791295Srobert const char *s; 50891295Srobert ino_t ino; 50991295Srobert ssize_t n; 51091295Srobert int dt; 51190699Srobert 51291295Srobert ino = ROOTINO; 51391295Srobert dt = DT_DIR; 51491678Srobert name[0] = '/'; 51591678Srobert name[1] = '\0'; 51691295Srobert for (;;) { 51791295Srobert if (*path == '/') 51891295Srobert path++; 51991295Srobert if (!*path) 52091295Srobert break; 52191295Srobert for (s = path; *s && *s != '/'; s++) 52291295Srobert ; 52391295Srobert if ((n = s - path) > MAXNAMLEN) 52491295Srobert return (0); 52591295Srobert ls = *path == '?' && n == 1 && !*s; 52691295Srobert memcpy(name, path, n); 52791295Srobert name[n] = 0; 52891678Srobert if (dt != DT_DIR) { 52991678Srobert printf("%s: not a directory.\n", name); 53091678Srobert return (0); 53191678Srobert } 53291295Srobert if ((dt = fsfind(name, &ino)) <= 0) 53391295Srobert break; 53491295Srobert path = s; 53591295Srobert } 53691295Srobert return (dt == DT_REG ? ino : 0); 53790699Srobert} 53890699Srobert 53990699Srobertstatic int 54090699Srobertxfsread(ino_t inode, void *buf, size_t nbyte) 54190699Srobert{ 54291295Srobert if (fsread(inode, buf, nbyte) != (ssize_t)nbyte) { 54391295Srobert printf("Invalid %s\n", "format"); 54491295Srobert return (-1); 54591295Srobert } 54691295Srobert return (0); 54790699Srobert} 54890699Srobert 54990699Srobertstatic ssize_t 55090699Srobertfsread(ino_t inode, void *buf, size_t nbyte) 55190699Srobert{ 55291295Srobert static struct fs fs; 55391295Srobert static struct dinode din; 55491295Srobert static char *blkbuf; 55591295Srobert static ufs_daddr_t *indbuf; 55691295Srobert static ino_t inomap; 55791295Srobert static ufs_daddr_t blkmap, indmap; 55891295Srobert static unsigned int fsblks; 55991295Srobert char *s; 56091295Srobert ufs_daddr_t lbn, addr; 56191295Srobert size_t n, nb, off; 56290699Srobert 56391295Srobert if (!dsk.meta) { 56491295Srobert if (!blkbuf) 56591295Srobert blkbuf = malloc(BSIZEMAX); 56691295Srobert inomap = 0; 56791295Srobert if (dskread(blkbuf, SBOFF / DEV_BSIZE, SBSIZE / DEV_BSIZE)) 56891295Srobert return (-1); 56991295Srobert memcpy(&fs, blkbuf, sizeof(fs)); 57091295Srobert if (fs.fs_magic != FS_MAGIC) { 57191295Srobert printf("Not ufs\n"); 57291295Srobert return (-1); 57391295Srobert } 57491295Srobert fsblks = fs.fs_bsize >> DEV_BSHIFT; 57591295Srobert dsk.meta++; 57690699Srobert } 57791295Srobert if (!inode) 57891295Srobert return (0); 57991295Srobert if (inomap != inode) { 58091295Srobert if (dskread(blkbuf, fsbtodb(&fs, ino_to_fsba(&fs, inode)), 58190699Srobert fsblks)) 58291295Srobert return (-1); 58391295Srobert din = ((struct dinode *)blkbuf)[inode % INOPB(&fs)]; 58491295Srobert inomap = inode; 58591295Srobert fs_off = 0; 58691295Srobert blkmap = indmap = 0; 58790699Srobert } 58891295Srobert s = buf; 58991295Srobert if (nbyte > (n = din.di_size - fs_off)) 59091295Srobert nbyte = n; 59191295Srobert nb = nbyte; 59291295Srobert while (nb) { 59391295Srobert lbn = lblkno(&fs, fs_off); 59491295Srobert if (lbn < NDADDR) 59591295Srobert addr = din.di_db[lbn]; 59691295Srobert else { 59791295Srobert if (indmap != din.di_ib[0]) { 59891295Srobert if (!indbuf) 59991295Srobert indbuf = malloc(BSIZEMAX); 60091295Srobert if (dskread(indbuf, fsbtodb(&fs, din.di_ib[0]), 60191295Srobert fsblks)) 60291295Srobert return (-1); 60391295Srobert indmap = din.di_ib[0]; 60491295Srobert } 60591295Srobert addr = indbuf[(lbn - NDADDR) % NINDIR(&fs)]; 60691295Srobert } 60791295Srobert n = dblksize(&fs, &din, lbn); 60891295Srobert if (blkmap != addr) { 60991295Srobert if (dskread(blkbuf, fsbtodb(&fs, addr), 61091295Srobert n >> DEV_BSHIFT)) { 61191295Srobert return (-1); 61291295Srobert } 61391295Srobert blkmap = addr; 61491295Srobert } 61591295Srobert off = blkoff(&fs, fs_off); 61691295Srobert n -= off; 61791295Srobert if (n > nb) 61891295Srobert n = nb; 61991295Srobert memcpy(s, blkbuf + off, n); 62091295Srobert s += n; 62191295Srobert fs_off += n; 62291295Srobert nb -= n; 62390699Srobert } 62491295Srobert return (nbyte); 62590699Srobert} 62690699Srobert 62790699Srobertstatic int 62890699Srobertdskread(void *buf, u_int64_t lba, int nblk) 62990699Srobert{ 63091295Srobert /* 63191295Srobert * The OpenFirmware should open the correct partition for us. 63291295Srobert * That means, if we read from offset zero on an open instance handle, 63391295Srobert * we should read from offset zero of that partition. 63491295Srobert */ 63591295Srobert ofw_seek(bootdevh, lba * DEV_BSIZE); 63691295Srobert ofw_read(bootdevh, buf, nblk * DEV_BSIZE); 63791295Srobert return (0); 63890699Srobert} 63990699Srobert 64090699Srobertstatic int 64190699Srobertprintf(const char *fmt,...) 64290699Srobert{ 64391295Srobert static const char digits[16] = "0123456789abcdef"; 64491295Srobert va_list ap; 64591295Srobert char buf[10]; 64691295Srobert char *s; 64791295Srobert unsigned long int r, u; 64891678Srobert int c, longp; 64990699Srobert 65091295Srobert va_start(ap, fmt); 65191678Srobert longp = 0; 65291295Srobert while ((c = *fmt++)) { 65391678Srobert if (c == '%' || longp) { 65491678Srobert if (c == '%') 65591678Srobert c = *fmt++; 65691295Srobert switch (c) { 65791295Srobert case 'c': 65891678Srobert if (longp) 65991678Srobert break; 66091295Srobert putchar(va_arg(ap, int)); 66191295Srobert continue; 66291295Srobert case 's': 66391678Srobert if (longp) 66491678Srobert break; 66591295Srobert for (s = va_arg(ap, char *); *s; s++) 66691295Srobert putchar(*s); 66791295Srobert continue; 66891295Srobert case 'p': 66991678Srobert if (longp) 67091678Srobert break; 67191295Srobert if (c == 'p') { 67291295Srobert putchar('0'); 67391295Srobert putchar('x'); 67491295Srobert } 67591295Srobert case 'u': 67691295Srobert case 'x': 67791295Srobert r = c == 'u' ? 10U : 16U; 67891678Srobert u = (c == 'p' || longp) ? 67991678Srobert va_arg(ap, unsigned long) : 68091295Srobert va_arg(ap, unsigned int); 68191295Srobert s = buf; 68291295Srobert do 68391295Srobert *s++ = digits[u % r]; 68491295Srobert while (u /= r); 68591295Srobert while (--s >= buf) 68691295Srobert putchar(*s); 68791678Srobert longp = 0; 68891295Srobert continue; 68991678Srobert case 'l': 69091678Srobert if (longp) 69191678Srobert break; 69291678Srobert longp = 1; 69391678Srobert continue; 69491295Srobert } 69591678Srobert longp = 0; 69690699Srobert } 69791295Srobert putchar(c); 69890699Srobert } 69991295Srobert va_end(ap); 70091295Srobert return (0); 70190699Srobert} 70290699Srobert 70390699Srobertstatic int 70490699Srobertputchar(int c) 70590699Srobert{ 70691295Srobert if (c == '\n') 70791295Srobert putc('\r'); 70891295Srobert putc(c); 70991295Srobert return (c); 71090699Srobert} 71190699Srobert 71290699Srobertstatic void * 71390699Srobertmemcpy(void *dst, const void *src, size_t size) 71490699Srobert{ 71591295Srobert const char *s; 71691295Srobert char *d; 71790699Srobert 71891295Srobert for (d = dst, s = src; size; size--) 71991295Srobert *d++ = *s++; 72091295Srobert return (dst); 72190699Srobert} 72290699Srobert 72390699Srobertstatic void * 72490699Srobertmalloc(size_t size) 72590699Srobert{ 72691295Srobert static vm_offset_t next = 0x10000; 72791295Srobert void *p; 72890699Srobert 72991295Srobert if (size & 0xf) 73091295Srobert size = (size + 0xf) & ~0xf; 73191295Srobert p = (void *)next; 73291295Srobert next += size; 73391295Srobert return (p); 73490699Srobert} 73590699Srobert 73690699Srobertstatic int 73790699Srobertkeyhit(unsigned int ticks) 73890699Srobert{ 73990699Srobert /* XXX */ 74091295Srobert return (0); 74190699Srobert ticks = ticks; /* make GCC happy */ 74290699Srobert} 74390699Srobert 74490699Srobertstatic int 74590699Srobertgetc(void) 74690699Srobert{ 74790699Srobert char c; 74890699Srobert ofw_read(stdinh, &c, 1); 74991295Srobert return (c); 75090699Srobert} 751