Sync usage with man page.
[netbsd-mini2440.git] / sys / arch / acorn26 / stand / boot26 / boot26.c
blob7fcca4a05f4e5c9ef0d96ce10549254f4be93ddf
1 /* $NetBSD: boot26.c,v 1.4 2005/12/11 12:16:05 christos Exp $ */
3 /*-
4 * Copyright (c) 1998, 1999, 2000, 2001 Ben Harris
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <lib/libkern/libkern.h>
31 #include <lib/libsa/stand.h>
32 #include <lib/libsa/loadfile.h>
33 #include <riscoscalls.h>
34 #include <sys/boot_flag.h>
35 #include <machine/boot.h>
36 #include <machine/memcreg.h>
38 extern const char bootprog_rev[];
39 extern const char bootprog_name[];
40 extern const char bootprog_date[];
41 extern const char bootprog_maker[];
43 int debug = 1;
45 enum pgstatus { FREE, USED_RISCOS, USED_KERNEL, USED_BOOT };
47 int nbpp;
48 struct os_mem_map_request *pginfo;
49 enum pgstatus *pgstatus;
51 u_long marks[MARK_MAX];
53 char fbuf[80];
55 void get_mem_map(struct os_mem_map_request *, enum pgstatus *, int);
56 int vdu_var(int);
58 extern void start_kernel(struct bootconfig *, u_int, u_int);
60 int
61 main(int argc, char **argv)
63 int npages, howto;
64 int i, j;
65 char *file;
66 struct bootconfig bootconfig;
67 int crow;
68 int ret;
70 printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
71 printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
73 os_read_mem_map_info(&nbpp, &npages);
74 if (debug)
75 printf("Machine has %d pages of %d KB each. "
76 "Total RAM: %d MB\n", npages, nbpp >> 10,
77 (npages * nbpp) >> 20);
79 /* Need one extra for teminator in OS_ReadMemMapEntries. */
80 pginfo = alloc((npages + 1) * sizeof(*pginfo));
81 if (pginfo == NULL)
82 panic("cannot alloc pginfo array");
83 memset(pginfo, 0, npages * sizeof(*pginfo));
84 pgstatus = alloc(npages * sizeof(*pgstatus));
85 if (pgstatus == NULL)
86 panic("cannot alloc pgstatus array");
87 memset(pgstatus, 0, npages * sizeof(*pgstatus));
89 get_mem_map(pginfo, pgstatus, npages);
91 howto = 0;
92 file = NULL;
93 for (i = 1; i < argc; i++)
94 if (argv[i][0] == '-')
95 for (j = 1; argv[i][j]; j++)
96 BOOT_FLAG(argv[i][j], howto);
97 else
98 if (file)
99 panic("Too many files!");
100 else
101 file = argv[i];
102 if (file == NULL) {
103 if (howto & RB_ASKNAME) {
104 printf("boot: ");
105 gets(fbuf);
106 file = fbuf;
107 } else
108 file = "netbsd";
110 printf("Booting %s (howto = 0x%x)\n", file, howto);
112 ret = loadfile(file, marks, LOAD_KERNEL);
113 if (ret == -1)
114 panic("Kernel load failed");
115 close(ret);
117 printf("Starting at 0x%lx\n", marks[MARK_ENTRY]);
119 memset(&bootconfig, 0, sizeof(bootconfig));
120 bootconfig.magic = BOOT_MAGIC;
121 bootconfig.version = 0;
122 bootconfig.boothowto = howto;
123 bootconfig.bootdev = -1;
124 bootconfig.ssym = (void *)marks[MARK_SYM] - MEMC_PHYS_BASE;
125 bootconfig.esym = (void *)marks[MARK_END] - MEMC_PHYS_BASE;
126 bootconfig.nbpp = nbpp;
127 bootconfig.npages = npages;
128 bootconfig.freebase = (void *)marks[MARK_END] - MEMC_PHYS_BASE;
129 bootconfig.xpixels = vdu_var(os_MODEVAR_XWIND_LIMIT) + 1;
130 bootconfig.ypixels = vdu_var(os_MODEVAR_YWIND_LIMIT) + 1;
131 bootconfig.bpp = 1 << vdu_var(os_MODEVAR_LOG2_BPP);
132 bootconfig.screenbase = (void *)vdu_var(os_VDUVAR_DISPLAY_START) +
133 vdu_var(os_VDUVAR_TOTAL_SCREEN_SIZE) - MEMC_PHYS_BASE;
134 bootconfig.screensize = vdu_var(os_VDUVAR_TOTAL_SCREEN_SIZE);
135 os_byte(osbyte_OUTPUT_CURSOR_POSITION, 0, 0, NULL, &crow);
136 bootconfig.cpixelrow = crow * vdu_var(os_VDUVAR_TCHAR_SPACEY);
138 if (bootconfig.bpp < 8)
139 printf("WARNING: Current screen mode has fewer than eight "
140 "bits per pixel.\n"
141 " Console display may not work correctly "
142 "(or at all).\n");
143 /* Tear down RISC OS... */
145 /* NetBSD will want the cache off initially. */
146 xcache_control(0, 0, NULL);
148 /* Dismount all filesystems. */
149 xosfscontrol_shutdown();
151 /* Ask device drivers to reset devices. */
152 service_pre_reset();
154 /* Disable interrupts. */
155 os_int_off();
157 start_kernel(&bootconfig, marks[MARK_ENTRY], 0x02090000);
159 return 0;
162 void
163 get_mem_map(struct os_mem_map_request *pginfo, enum pgstatus *pgstatus,
164 int npages)
166 int i;
168 for (i = 0; i < npages; i++)
169 pginfo[i].page_no = i;
170 pginfo[npages].page_no = -1;
171 os_read_mem_map_entries(pginfo);
173 if (debug)
174 printf("--------/-------/-------/-------\n");
175 for (i = 0; i < npages; i++) {
176 pgstatus[i] = USED_RISCOS;
177 if (pginfo[i].access == os_AREA_ACCESS_NONE) {
178 if (debug) printf(".");
179 } else {
180 if (pginfo[i].map < (void *)0x0008000) {
181 if (debug) printf("0");
182 } else if (pginfo[i].map < (void *)HIMEM) {
183 pgstatus[i] = USED_BOOT;
184 if (debug) printf("+");
185 } else if (pginfo[i].map < (void *)0x1000000) {
186 if (pginfo[i].access ==
187 os_AREA_ACCESS_READ_WRITE) {
188 pgstatus[i] = FREE;
189 if (debug) printf("*");
190 } else {
191 if (debug) printf("a");
193 } else if (pginfo[i].map < (void *)0x1400000) {
194 if (debug) printf("d");
195 } else if (pginfo[i].map < (void *)0x1800000) {
196 if (debug) printf("s");
197 } else if (pginfo[i].map < (void *)0x1c00000) {
198 if (debug) printf("m");
199 } else if (pginfo[i].map < (void *)0x1e00000) {
200 if (debug) printf("h");
201 } else if (pginfo[i].map < (void *)0x1f00000) {
202 if (debug) printf("f");
203 } else if (pginfo[i].map < (void *)0x2000000) {
204 if (debug) printf("S");
207 if (i % 32 == 31 && debug)
208 printf("\n");
213 * Return the address of a page that will end up corresponding to the
214 * target address when the kernel boots. "target" is expected to be
215 * in the MEMC physical RAM area (0x02000000--0x02ffffff). It need
216 * not be page-aligned. The return value is in the logical RAM area,
217 * and either points to a mapping of the requested page or to a
218 * mapping of another page which will be copied to the requested page
219 * after RISC OS is shut down.
221 * At present, there's no relocation mechanism, so we panic if its use
222 * is required.
224 static void *
225 get_page(void *target)
227 int ppn;
229 ppn = ((void *)target - MEMC_PHYS_BASE) / nbpp;
230 if (pgstatus[ppn] != FREE)
231 panic("Page %d not free", ppn);
232 return pginfo[ppn].map;
235 ssize_t
236 boot26_read(int f, void *addr, size_t size)
238 void *fragaddr;
239 size_t fragsize;
240 ssize_t retval, total;
242 total = 0;
243 while (size > 0) {
244 fragaddr = get_page(addr) + ((u_int)addr % nbpp);
245 fragsize = nbpp - ((u_int)addr % nbpp);
246 if (fragsize > size)
247 fragsize = size;
248 retval = read(f, fragaddr, fragsize);
249 if (retval < 0)
250 return retval;
251 total += retval;
252 if (retval < fragsize)
253 return total;
254 addr += fragsize;
255 size -= fragsize;
257 return total;
260 void *
261 boot26_memcpy(void *dst, const void *src, size_t size)
263 void *fragaddr;
264 size_t fragsize;
265 void *addr = dst;
267 while (size > 0) {
268 fragaddr = get_page(addr) + ((u_int)addr % nbpp);
269 fragsize = nbpp - ((u_int)addr % nbpp);
270 if (fragsize > size)
271 fragsize = size;
272 memcpy(fragaddr, src, fragsize);
273 addr += fragsize;
274 src += fragsize;
275 size -= fragsize;
277 return dst;
280 void *
281 boot26_memset(void *dst, int c, size_t size)
283 void *fragaddr;
284 size_t fragsize;
285 void *addr = dst;
287 while (size > 0) {
288 fragaddr = get_page(addr) + ((u_int)addr % nbpp);
289 fragsize = nbpp - ((u_int)addr % nbpp);
290 if (fragsize > size)
291 fragsize = size;
292 memset(fragaddr, c, fragsize);
293 addr += fragsize;
294 size -= fragsize;
296 return dst;
300 vdu_var(int var)
302 int varlist[2], vallist[2];
304 varlist[0] = var;
305 varlist[1] = -1;
306 os_read_vdu_variables(varlist, vallist);
307 return vallist[0];