Print this page
first pass
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/psm/stand/boot/sparc/common/ramdisk.c
+++ new/usr/src/psm/stand/boot/sparc/common/ramdisk.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 #include <sys/param.h>
27 27 #include <sys/promif.h>
28 28 #include <sys/salib.h>
29 -/* EXPORT DELETE START */
30 29 #include <bootlog.h>
31 -/* EXPORT DELETE END */
32 30 #include "ramdisk.h"
33 31
34 32 #include <sys/param.h>
35 33 #include <sys/fcntl.h>
36 34 #include <sys/obpdefs.h>
37 35 #include <sys/reboot.h>
38 36 #include <sys/promif.h>
39 37 #include <sys/stat.h>
40 38 #include <sys/bootvfs.h>
41 39 #include <sys/platnames.h>
42 40 #include <sys/salib.h>
43 41 #include <sys/elf.h>
44 42 #include <sys/link.h>
45 43 #include <sys/auxv.h>
46 44 #include <sys/boot_policy.h>
47 45 #include <sys/boot_redirect.h>
48 46 #include <sys/bootconf.h>
49 47 #include <sys/boot.h>
50 48 #include "boot_plat.h"
51 49
52 50
53 51 static char ramdisk_preamble_fth[] =
54 52
55 53 ": find-abort ( name$ -- ) "
56 54 " .\" Can't find \" type abort "
57 55 "; "
58 56
59 57 ": get-package ( pkg$ -- ph ) "
60 58 " 2dup find-package 0= if "
61 59 " find-abort "
62 60 " then ( pkg$ ph ) "
63 61 " nip nip ( ph ) "
64 62 "; "
65 63
66 64 "\" /openprom/client-services\" get-package constant cif-ph "
67 65
68 66 "instance defer cif-open ( dev$ -- ihandle|0 ) "
69 67 "instance defer cif-close ( ihandle -- ) "
70 68
71 69 ": find-cif-method ( adr,len -- acf ) "
72 70 " 2dup cif-ph find-method 0= if ( adr,len ) "
73 71 " find-abort "
74 72 " then ( adr,len acf ) "
75 73 " nip nip ( acf ) "
76 74 "; "
77 75
78 76 "\" open\" find-cif-method to cif-open "
79 77 "\" close\" find-cif-method to cif-close "
80 78
81 79 "0 value dev-ih "
82 80
83 81 "d# 100 buffer: open-cstr "
84 82
85 83 ": dev-open ( dev$ -- okay? ) "
86 84 /* copy to C string for open */
87 85 " 0 over open-cstr + c! "
88 86 " open-cstr swap move "
89 87 " open-cstr cif-open dup if "
90 88 " dup to dev-ih "
91 89 " then "
92 90 "; "
93 91
94 92 ": dev-close ( -- ) "
95 93 " dev-ih cif-close "
96 94 " 0 to dev-ih "
97 95 "; "
98 96
99 97 ": open-abort ( file$ -- ) "
100 98 " .\" Can't open \" type abort "
101 99 "; "
102 100 ;
103 101
104 102 static char ramdisk_fth[] =
105 103
106 104 "\" /\" get-package push-package "
107 105
108 106 "new-device "
109 107 " \" %s\" device-name "
110 108 " "
111 109 " \" block\" device-type "
112 110 " \" SUNW,ramdisk\" encode-string \" compatible\" property"
113 111
114 112 " 0 instance value current-offset "
115 113 " "
116 114 " 0 value ramdisk-base-va "
117 115 " 0 value ramdisk-size "
118 116 " 0 value alloc-size "
119 117 " "
120 118 " : set-props "
121 119 " ramdisk-size encode-int \" size\" property "
122 120 " ramdisk-base-va encode-int \" address\" property "
123 121 " alloc-size encode-int \" alloc-size\" property "
124 122 " ; "
125 123 " set-props "
126 124 " "
127 125 " : current-va ( -- adr ) ramdisk-base-va current-offset + ; "
128 126 " "
129 127 " external "
130 128 " "
131 129 " : open ( -- okay? ) "
132 130 /* " .\" ramdisk-open\" cr " */
133 131 " true "
134 132 " ; "
135 133 " "
136 134 " : close ( -- ) "
137 135 " ; "
138 136 " "
139 137 " : seek ( off.low off.high -- error? ) "
140 138 /* " 2dup .\" ramdisk-seek: \" .x .x " */
141 139 " drop dup ramdisk-size > if "
142 140 /* " .\" fail\" cr " */
143 141 " drop true exit ( failed ) "
144 142 " then "
145 143 " to current-offset false ( succeeded ) "
146 144 /* " .\" OK\" cr " */
147 145 " ; "
148 146 " "
149 147 " : read ( addr len -- actual-len ) "
150 148 /* " 2dup .\" ramdisk-read: \" .x .x " */
151 149 " dup current-offset + ( addr len new-off ) "
152 150 " dup ramdisk-size > if "
153 151 " ramdisk-size - - ( addr len' ) "
154 152 " ramdisk-size ( addr len new-off ) "
155 153 " then -rot ( new-off addr len ) "
156 154 " tuck current-va -rot move ( new-off len ) "
157 155 " swap to current-offset ( len ) "
158 156 /* " dup .x cr " */
159 157 " ; "
160 158 " "
161 159 " : create ( alloc-sz base size -- ) "
162 160 " to ramdisk-size "
163 161 " to ramdisk-base-va "
164 162 " to alloc-size "
165 163 " set-props "
166 164 " ; "
167 165 " "
168 166 "finish-device "
169 167 "pop-package "
170 168
171 169 "\" /%s\" 2dup dev-open 0= if "
172 170 " open-abort "
173 171 "then 2drop "
174 172
175 173 /* %x %x %x will be replaced by alloc-sz, base, size respectively */
176 174 "h# %x h# %x h# %x ( alloc-sz base size ) "
177 175 "\" create\" dev-ih $call-method ( ) "
178 176 "dev-close "
179 177
180 178 ;
181 179
182 180 char ramdisk_bootable[] =
183 181
184 182 "\" /chosen\" get-package push-package "
185 183 " \" nfs\" encode-string \" fstype\" property "
186 184 " \" /%s\" encode-string \" bootarchive\" property "
187 185 "pop-package "
188 186
189 187 " h# %x d# 512 + to load-base init-program "
190 188 ;
191 189
192 190 #define BOOT_ARCHIVE_ALLOC_SIZE (32 * 1024 * 1024) /* 32 MB */
193 191 #define BOOTFS_VIRT ((caddr_t)0x50f00000)
194 192 #define ROOTFS_VIRT ((caddr_t)0x52000000)
195 193
196 194 struct ramdisk_attr {
197 195 char *rd_name;
198 196 caddr_t rd_base;
199 197 size_t rd_size;
200 198 } ramdisk_attr[] = {
201 199 RD_BOOTFS, BOOTFS_VIRT, 0,
202 200 RD_ROOTFS, ROOTFS_VIRT, 0,
203 201 0
204 202 };
205 203
206 204 static struct ramdisk_attr *
207 205 ramdisk_lookup(char *ramdisk_name)
208 206 {
209 207 int i;
210 208
211 209 for (i = 0; ramdisk_attr[i].rd_name != 0; i++) {
212 210 if (strcmp(ramdisk_name, ramdisk_attr[i].rd_name) == 0) {
213 211 return (&ramdisk_attr[i]);
214 212 }
215 213 }
216 214 return (NULL);
217 215 }
218 216
219 217 static void
220 218 ramdisk_free_mem(caddr_t addr, size_t size)
221 219 {
222 220 caddr_t end_addr;
223 221
224 222 for (end_addr = addr + size; addr < end_addr;
225 223 addr += BOOT_ARCHIVE_ALLOC_SIZE) {
226 224 prom_free(addr, MIN(BOOT_ARCHIVE_ALLOC_SIZE, end_addr - addr));
227 225 }
228 226 }
229 227
230 228 /*
231 229 * Allocate memory for ramdisk image.
232 230 */
233 231 static caddr_t
234 232 ramdisk_alloc_mem(caddr_t addr, size_t size)
235 233 {
236 234 caddr_t virt = addr;
237 235 caddr_t end_addr;
238 236
239 237 for (end_addr = virt + size; virt < end_addr;
240 238 virt += BOOT_ARCHIVE_ALLOC_SIZE) {
241 239 if (prom_alloc(virt,
242 240 MIN(BOOT_ARCHIVE_ALLOC_SIZE, end_addr - virt),
243 241 1) == NULL) {
244 242 ramdisk_free_mem(addr, virt - addr);
245 243 return (NULL);
246 244 }
247 245 }
248 246 return (addr);
249 247 }
250 248
251 249 caddr_t
252 250 create_ramdisk(char *ramdisk_name, size_t size, char **devpath)
253 251 {
254 252 char *fth_buf;
255 253 size_t buf_size;
256 254 struct ramdisk_attr *rdp;
257 255 char tdevpath[80];
258 256 caddr_t virt;
259 257 static int need_preamble = 1;
260 258
261 259 /*
262 260 * lookup ramdisk name.
263 261 */
264 262 if ((rdp = ramdisk_lookup(ramdisk_name)) == NULL)
265 263 prom_panic("invalid ramdisk name");
266 264
267 265 virt = rdp->rd_base;
268 266
269 267 /*
270 268 * Allocate memory.
271 269 */
272 270 size = roundup(size, PAGESIZE);
273 271 if (ramdisk_alloc_mem(virt, size) == NULL)
274 272 prom_panic("can't alloc ramdisk memory");
275 273
276 274 rdp->rd_size = size;
277 275
278 276 if (need_preamble) {
279 277 prom_interpret(ramdisk_preamble_fth, 0, 0, 0, 0, 0);
280 278 need_preamble = 0;
281 279 }
282 280
283 281 /*
284 282 * add some space to the size to accommodate a few words in the
285 283 * snprintf() below.
286 284 */
287 285 buf_size = sizeof (ramdisk_fth) + 80;
288 286
289 287 fth_buf = bkmem_alloc(buf_size);
290 288 if (fth_buf == NULL)
291 289 prom_panic("unable to allocate Forth buffer for ramdisk");
292 290
293 291 (void) snprintf(fth_buf, buf_size, ramdisk_fth,
294 292 ramdisk_name, ramdisk_name,
295 293 BOOT_ARCHIVE_ALLOC_SIZE, virt, size);
296 294
297 295 prom_interpret(fth_buf, 0, 0, 0, 0, 0);
298 296 bkmem_free(fth_buf, buf_size);
299 297
300 298 if (devpath != NULL) {
301 299 (void) snprintf(tdevpath, sizeof (tdevpath), "/%s:nolabel",
302 300 ramdisk_name);
303 301 *devpath = strdup(tdevpath);
304 302 }
305 303
306 304 return (virt);
307 305 }
308 306
309 307 void
310 308 destroy_ramdisk(char *ramdisk_name)
311 309 {
312 310 struct ramdisk_attr *rdp;
313 311
314 312 /*
315 313 * lookup ramdisk name.
316 314 */
317 315 if ((rdp = ramdisk_lookup(ramdisk_name)) == NULL)
318 316 prom_panic("invalid ramdisk name");
319 317
320 318 ramdisk_free_mem(rdp->rd_base, rdp->rd_size);
321 319 rdp->rd_size = 0;
322 320 }
323 321
324 322 /*
325 323 * change cwp! to drop in the 2nd word of (init-program) - really
326 324 * init-c-stack, but that word has no header.
327 325 * (you are not expected to undertsnad this)
328 326 */
329 327 char obpfix[] = "' drop ' cwp! ' (init-program) >body ta1+ token@ (patch";
330 328 char obpver[OBP_MAXPROPNAME];
331 329 const char badver[] = "OBP 4.27.";
332 330
333 331
334 332 void
335 333 boot_ramdisk(char *ramdisk_name)
336 334 {
337 335 char *fth_buf;
338 336 size_t buf_size;
339 337 struct ramdisk_attr *rdp;
340 338 void do_sg_go(void);
341 339
342 340 /*
343 341 * OBP revs 4.27.0 to 4.27.8 started using
344 342 * windowed regs for the forth kernel, but
345 343 * init-program still blindly 0'd %cwp, which
346 344 * causes predictably disaterous consequences
347 345 * when called with %cwp != 0.
348 346 *
349 347 * We detect and fix this here
350 348 */
351 349 if (prom_version_name(obpver, OBP_MAXPROPNAME) != -1 &&
352 350 strncmp(obpver, badver, sizeof (badver) - 1) == 0) {
353 351 char ch = obpver[sizeof (badver) - 1];
354 352
355 353 if (ch >= '0' && ch <= '8') {
356 354 prom_interpret(obpfix, 0, 0, 0, 0, 0);
357 355 }
358 356 }
359 357
360 358 /* close all open devices */
361 359 closeall(1);
362 360
363 361 /*
364 362 * lookup ramdisk name.
365 363 */
366 364 if ((rdp = ramdisk_lookup(ramdisk_name)) == NULL)
367 365 prom_panic("invalid ramdisk name");
368 366
369 367 /*
370 368 * add some space to the size to accommodate a few words in the
371 369 * snprintf() below.
372 370 */
373 371 buf_size = sizeof (ramdisk_bootable) + 80;
374 372
375 373 fth_buf = bkmem_alloc(buf_size);
376 374 if (fth_buf == NULL)
377 375 prom_panic("unable to allocate Forth buffer for ramdisk");
378 376
379 377 (void) snprintf(fth_buf, buf_size, ramdisk_bootable,
380 378 ramdisk_name, rdp->rd_base);
381 379
382 380 prom_interpret(fth_buf, 0, 0, 0, 0, 0);
383 381
384 382 /*
385 383 * Ugh Serengeti proms don't execute C programs
386 384 * in init-program, and 'go' doesn't work when
387 385 * launching a second C program (inetboot itself
388 386 * was launched as the 1st C program). Nested fcode
389 387 * programs work, but that doesn't help the kernel.
390 388 */
391 389 do_sg_go();
392 390 }
393 391
394 392 void
395 393 do_sg_go()
396 394 {
397 395 pnode_t chosen = prom_chosennode();
398 396 Elf64_Ehdr *ehdr;
399 397 Elf64_Addr entry;
400 398 uint32_t eadr;
401 399 extern int is_sg;
402 400 extern caddr_t sg_addr;
403 401 extern size_t sg_len;
404 402
405 403 if (!is_sg)
406 404 prom_panic("do_sg_go");
407 405
408 406 /*
409 407 * The ramdisk bootblk left a pointer to the elf image
410 408 * in 'elfheader-address' Use it to find the kernel's
411 409 * entry point.
412 410 */
413 411 if (prom_getprop(chosen, "elfheader-address", (caddr_t)&eadr) == -1)
414 412 prom_panic("no elf header property");
415 413 ehdr = (Elf64_Ehdr *)(uintptr_t)eadr;
416 414 if (ehdr->e_machine != EM_SPARCV9)
417 415 prom_panic("bad ELF header");
418 416 entry = ehdr->e_entry;
419 417
420 418 /*
421 419 * free extra bootmem
422 420 */
423 421 prom_free(sg_addr, sg_len);
424 422
425 423 /*
426 424 * Use pre-newboot's exitto64() to launch the kernel
427 425 */
428 426 exitto64((int (*)())entry, NULL);
429 427 prom_panic("exitto returned");
430 428 }
↓ open down ↓ |
389 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX