1/*-
|
2 * Copyright (c) 2008 John Hay 3 * Copyright (c) 2006 Warner Losh |
4 * Copyright (c) 1998 Robert Nordier 5 * All rights reserved. 6 * 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 10 * such forms. 11 * 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 15 * purpose. 16 */ 17 18#include <sys/cdefs.h>
|
17__FBSDID("$FreeBSD: head/sys/boot/arm/at91/boot2/boot2.c 183635 2008-10-05 23:39:28Z imp $");
|
19__FBSDID("$FreeBSD: head/sys/boot/arm/at91/boot2/boot2.c 183636 2008-10-05 23:59:52Z imp $"); |
20 21#include <sys/param.h> 22#include <sys/disklabel.h> 23#include <sys/diskmbr.h> 24#include <sys/dirent.h> 25#include <sys/reboot.h> 26 27#include <machine/elf.h> 28 29#include <stdarg.h> 30 31#include "lib.h" 32#include "board.h" 33 34#define RBX_ASKNAME 0x0 /* -a */ 35#define RBX_SINGLE 0x1 /* -s */ 36/* 0x2 is reserved for log2(RB_NOSYNC). */ 37/* 0x3 is reserved for log2(RB_HALT). */ 38/* 0x4 is reserved for log2(RB_INITNAME). */ 39#define RBX_DFLTROOT 0x5 /* -r */ 40/* #define RBX_KDB 0x6 -d */ 41/* 0x7 is reserved for log2(RB_RDONLY). */ 42/* 0x8 is reserved for log2(RB_DUMP). */ 43/* 0x9 is reserved for log2(RB_MINIROOT). */ 44#define RBX_CONFIG 0xa /* -c */ 45#define RBX_VERBOSE 0xb /* -v */ 46/* #define RBX_SERIAL 0xc -h */ 47/* #define RBX_CDROM 0xd -C */ 48/* 0xe is reserved for log2(RB_POWEROFF). */ 49#define RBX_GDB 0xf /* -g */ 50/* #define RBX_MUTE 0x10 -m */ 51/* 0x11 is reserved for log2(RB_SELFTEST). */ 52/* 0x12 is reserved for boot programs. */ 53/* 0x13 is reserved for boot programs. */ 54/* #define RBX_PAUSE 0x14 -p */ 55/* #define RBX_QUIET 0x15 -q */
|
54/* #define RBX_NOINTR 0x1c -n */
|
56#define RBX_NOINTR 0x1c /* -n */ |
57/* 0x1d is reserved for log2(RB_MULTIPLE) and is just misnamed here. */ 58/* #define RBX_DUAL 0x1d -D */ 59/* 0x1f is reserved for log2(RB_BOOTINFO). */ 60 61/* pass: -a, -s, -r, -v, -g */ 62#define RBX_MASK (OPT_SET(RBX_ASKNAME) | OPT_SET(RBX_SINGLE) | \ 63 OPT_SET(RBX_DFLTROOT) | \ 64 OPT_SET(RBX_VERBOSE) | \ 65 OPT_SET(RBX_GDB)) 66 67#define PATH_CONFIG "/boot.config" 68//#define PATH_KERNEL "/boot/kernel/kernel" 69#define PATH_KERNEL "/boot/kernel/kernel.gz.tramp" 70
|
69#define NOPT 5
|
71extern uint32_t _end; |
72
|
73#define NOPT 6 74 |
75#define OPT_SET(opt) (1 << (opt)) 76#define OPT_CHECK(opt) ((opts) & OPT_SET(opt)) 77
|
74extern uint32_t _end;
75
76static const char optstr[NOPT] = "agrsv";
|
78static const char optstr[NOPT] = "agnrsv"; |
79static const unsigned char flags[NOPT] = {
|
78 RBX_ASKNAME,
79 RBX_GDB,
80 RBX_DFLTROOT,
81 RBX_SINGLE,
82 RBX_VERBOSE
|
80 RBX_ASKNAME, 81 RBX_GDB, 82 RBX_NOINTR, 83 RBX_DFLTROOT, 84 RBX_SINGLE, 85 RBX_VERBOSE |
86}; 87 88unsigned dsk_start; 89static char cmd[512]; 90static char kname[1024]; 91static uint32_t opts; 92static int dsk_meta; 93 94static void load(void); 95static int parse(void); 96static int xfsread(ino_t, void *, size_t); 97static int dskread(void *, unsigned, unsigned); 98 99#define UFS_SMALL_CGBASE 100#include "ufsread.c" 101
|
102#ifdef DEBUG 103#define DPRINTF(fmt, ...) printf(fmt, __VA_ARGS__) 104#else 105#define DPRINTF(fmt, ...) 106#endif 107 |
108static inline int 109xfsread(ino_t inode, void *buf, size_t nbyte) 110{ 111 if ((size_t)fsread(inode, buf, nbyte) != nbyte) 112 return -1; 113 return 0; 114} 115 116static inline void 117getstr(int c) 118{ 119 char *s; 120 121 s = cmd; 122 if (c == 0) 123 c = getc(10000); 124 for (;;) { 125 switch (c) { 126 case 0: 127 break; 128 case '\177': 129 case '\b': 130 if (s > cmd) { 131 s--; 132 printf("\b \b"); 133 } 134 break; 135 case '\n': 136 case '\r': 137 *s = 0; 138 return; 139 default: 140 if (s - cmd < sizeof(cmd) - 1) 141 *s++ = c; 142 xputchar(c); 143 } 144 c = getc(10000); 145 } 146} 147 148int 149main(void) 150{ 151 int autoboot, c = 0; 152 ino_t ino; 153
|
154 dmadat = (void *)(0x20000000 + (16 << 20)); |
155 board_init(); 156
|
147 dmadat = (void *)(0x20000000 + (16 << 20));
148 /* Process configuration file */
149
|
157 autoboot = 1; 158
|
159 /* Process configuration file */ |
160 if ((ino = lookup(PATH_CONFIG))) 161 fsread(ino, cmd, sizeof(cmd)); 162 163 if (*cmd) { 164 if (parse()) 165 autoboot = 0;
|
158 printf("%s: %s", PATH_CONFIG, cmd);
|
166 printf("%s: %s\n", PATH_CONFIG, cmd); |
167 /* Do not process this command twice */ 168 *cmd = 0; 169 } 170
|
163 /* Present the user with the boot2 prompt. */
164
|
171 if (*kname == '\0') 172 strcpy(kname, PATH_KERNEL);
|
173 174 /* Present the user with the boot2 prompt. */ |
175 for (;;) { 176 printf("\nDefault: %s\nboot: ", kname);
|
169 if (!autoboot || (c = getc(2)) != -1)
|
177 if (!autoboot || 178 (OPT_CHECK(RBX_NOINTR) == 0 && (c = getc(2)) != 0)) |
179 getstr(c); 180 xputchar('\n'); 181 autoboot = 0; 182 c = 0; 183 if (parse()) 184 xputchar('\a'); 185 else 186 load(); 187 } 188} 189 190static void 191load(void) 192{ 193 Elf32_Ehdr eh; 194 static Elf32_Phdr ep[2]; 195 caddr_t p; 196 ino_t ino; 197 uint32_t addr; 198 int i, j; 199 200 if (!(ino = lookup(kname))) { 201 if (!ls) 202 printf("No %s\n", kname); 203 return; 204 } 205 if (xfsread(ino, &eh, sizeof(eh))) 206 return; 207 if (!IS_ELF(eh)) { 208 printf("Invalid %s\n", "format"); 209 return; 210 } 211 fs_off = eh.e_phoff; 212 for (j = i = 0; i < eh.e_phnum && j < 2; i++) { 213 if (xfsread(ino, ep + j, sizeof(ep[0]))) 214 return; 215 if (ep[j].p_type == PT_LOAD) 216 j++; 217 } 218 for (i = 0; i < 2; i++) { 219 p = (caddr_t)ep[i].p_paddr; 220 fs_off = ep[i].p_offset; 221 if (xfsread(ino, p, ep[i].p_filesz)) 222 return; 223 } 224 addr = eh.e_entry; 225 ((void(*)(int))addr)(opts & RBX_MASK); 226} 227 228static int 229parse() 230{ 231 char *arg = cmd; 232 char *ep, *p; 233 int c, i; 234 235 while ((c = *arg++)) { 236 if (c == ' ' || c == '\t' || c == '\n') 237 continue; 238 for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++); 239 ep = p; 240 if (*p) 241 *p++ = 0; 242 if (c == '-') { 243 while ((c = *arg++)) { 244 for (i = 0; c != optstr[i]; i++) 245 if (i == NOPT - 1) 246 return -1; 247 opts ^= OPT_SET(flags[i]); 248 } 249 } else { 250 arg--; 251 if ((i = ep - arg)) { 252 if ((size_t)i >= sizeof(kname)) 253 return -1; 254 memcpy(kname, arg, i + 1); 255 } 256 } 257 arg = p; 258 } 259 return 0; 260} 261 262static int 263dskread(void *buf, unsigned lba, unsigned nblk) 264{ 265 struct dos_partition *dp; 266 struct disklabel *d; 267 char *sec; 268 int i; 269 270 if (!dsk_meta) { 271 sec = dmadat->secbuf; 272 dsk_start = 0; 273 if (drvread(sec, DOSBBSECTOR, 1)) 274 return -1; 275 dp = (void *)(sec + DOSPARTOFF); 276 for (i = 0; i < NDOSPART; i++) { 277 if (dp[i].dp_typ == DOSPTYP_386BSD) 278 break; 279 } 280 if (i == NDOSPART) 281 return -1; 282 /* 283 * Although dp_start is aligned within the disk 284 * partition structure, DOSPARTOFF is 446, which is 285 * only word (2) aligned, not longword (4) aligned. 286 * Cope by using memcpy to fetch the start of this 287 * partition. 288 */ 289 memcpy(&dsk_start, &dp[1].dp_start, 4); 290 if (drvread(sec, dsk_start + LABELSECTOR, 1)) 291 return -1; 292 d = (void *)(sec + LABELOFFSET); 293 if (d->d_magic != DISKMAGIC || d->d_magic2 != DISKMAGIC) { 294 printf("Invalid %s\n", "label"); 295 return -1; 296 } 297 if (!d->d_partitions[0].p_size) { 298 printf("Invalid %s\n", "partition"); 299 return -1; 300 } 301 dsk_start += d->d_partitions[0].p_offset; 302 dsk_start -= d->d_partitions[RAW_PART].p_offset; 303 dsk_meta++; 304 } 305 return drvread(buf, dsk_start + lba, nblk); 306}
|