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