Deleted Added
full compact
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}