4 \ The contents of this file are subject to the terms of the
5 \ Common Development and Distribution License (the "License").
6 \ You may not use this file except in compliance with the License.
8 \ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 \ or http://www.opensolaris.org/os/licensing.
10 \ See the License for the specific language governing permissions
11 \ and limitations under the License.
13 \ When distributing Covered Code, include this CDDL HEADER in each
14 \ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 \ If applicable, add the following below this CDDL HEADER, with the
16 \ fields enclosed by brackets "[]" replaced with your own identifying
17 \ information: Portions Copyright [yyyy] [name of copyright owner]
22 \ Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 \ Use is subject to license terms.
26 purpose: boot block for OBP systems
27 copyright: Copyright 2009 Sun Microsystems, Inc. All Rights Reserved
31 d# 1024 dup * constant 1meg
32 d# 4 1meg * constant 4meg
33 d# 32 1meg * constant 32meg
36 " /" get-package constant root-ph
42 /buf-len buffer: boot-dev
43 : boot-dev$ ( -- dev$ ) boot-dev cscount ;
45 : loader-base ( -- base )
55 \ methods we expect of fs reader packages
58 : fs-open ( file$ -- fd true | false )
59 " open-file" fs-ih $call-method
63 " close-file" fs-ih $call-method
66 : fs-size ( fd -- size )
67 " size-file" fs-ih $call-method
70 : fs-read ( adr len fd -- #read )
71 " read-file" fs-ih $call-method
74 : fs-getrd ( adr len -- )
75 " get-rd" fs-ih $call-method
78 : fs-bootprop ( -- propval propname true | false )
79 " bootprop" fs-ih $call-method
84 : check-elf ( base -- is-elf? )
85 l@ h# 7f454c46 ( \x7fELF ) =
88 : check-fcode ( base -- is-fcode? )
89 c@ dup h# f0 h# f3 between swap h# fd = or
93 \ zfs bootblks with all headers exceeds 7.5k
94 \ 'bigbootblk' allows us to load the fs reader from elsewhere
99 2dup dev-open ?dup 0= if
101 then >r 2drop ( r: ih )
103 /fs-fcode mem-alloc ( adr r: ih )
104 dup /fs-fcode fs-offset r@ read-disk
106 dup check-fcode invert if
107 " No fs fcode found" die
111 /fs-fcode mem-free ( r: ih )
123 \ first try boot archive (nested boot from ramdisk)
124 \ then try boot device (direct boot from disk)
125 " bootarchive" chosen-ph get-package-property if
126 " bootpath" chosen-ph get-string-prop ( bootpath$ )
127 else ( archiveprop$ )
128 decode-string 2swap 2drop ( archivepath$ )
131 boot-dev swap move ( )
135 boot-dev$ fs-pkg$ $open-package to fs-ih
137 " Can't mount root" die
142 \ cheap entertainment for those watching
147 ascii | c, ascii / c, ascii - c, ascii \ c,
153 spindex @ 3 and spin-data + ( c-adr )
158 \ allocate and return physical allocation size
159 : vmem-alloc-prop ( size virt -- alloc-size virt )
160 2dup ['] vmem-alloc catch if ( size virt ??? ??? )
162 2dup begin ( size virt len adr )
163 over 32meg min >r ( size virt len adr r: alloc-sz )
164 r@ over vmem-alloc ( size virt len adr adr r: alloc-sz )
165 nip r@ + ( size virt len adr' r: alloc-sz )
166 swap r> - ( size virt adr len' )
167 swap over 0= ( size virt len' adr done? )
168 until ( size virt len' adr )
169 2drop nip 32meg ( virt 32meg )
170 else ( size virt virt )
172 then ( virt alloc-sz )
176 \ read file in chunks so we can toggle the spinner
177 : read-file ( virt size fd -- failed? )
178 >r ( virt sz-left r: fd )
181 dup 4meg min ( virt sz-left read-sz r: fd )
182 3dup nip r@ fs-read ( virt sz-left read-sz size-read r: fd )
183 over <> if ( virt sz-left read-sz r: fd )
187 rot over + ( sz-left read-sz virt' r: fd )
188 -rot - ( virt' sz-left' r: fd )
194 \ read in file and return buffer
195 \ if base==0, vmem-alloc will allocate virt
196 \ NB returned size is 8k rounded since the
197 \ memory allocator rounded it for us
198 : get-file ( base fd -- [ alloc-sz virt size ] failed? )
199 dup >r fs-size ( base size r: fd )
200 dup rot vmem-alloc-prop ( size alloc-sz virt r: fd )
201 rot 2dup ( alloc-sz virt size virt size r: fd )
202 r> read-file if ( alloc-sz virt size )
203 3drop true exit ( failed )
205 h# 2000 roundup ( alloc-sz virt size' )
206 false ( alloc-sz virt size' succeeded )
211 false value is-archive?
214 : >bootblk ( adr -- adr' ) d# 512 + ;
216 \ figure out what we just loaded
217 : get-type ( adr -- )
218 dup check-elf to is-elf?
220 \ if not nested, check for boot archive (executable after label)
223 dup check-fcode ( adr is-fcode? )
224 over check-elf ( adr is-fcode? is-elf? )
235 \ boot file (-F name or boot archive)
237 /buf-len buffer: boot-file
238 : boot-file$ ( -- file$ ) boot-file cscount ;
240 \ kernel name (final name or unix)
242 /buf-len buffer: kern-file
243 : kern-file$ ( -- file$ ) kern-file cscount ;
246 /buf-len buffer: plat-name
247 : plat-name$ ( -- plat$ ) plat-name cscount ;
250 /buf-len buffer: arch-name
251 : arch-name$ ( -- arch$ ) arch-name cscount ;
253 \ final name after /platform massaging
254 /buf-len buffer: targ-file
255 : targ-file$ ( -- file$ ) targ-file cscount ;
258 targ-file /buf-len erase
259 " /platform/" targ-file swap move
262 \ remove illegal file name chars (e.g., '/')
263 : munge-name ( name$ -- name$' )
267 over ascii _ swap c! ( name$ name$' )
269 repeat 2drop ( name$ )
272 \ does /platform/<name> exist?
273 : try-platname ( name$ -- name$ true | false )
274 munge-name ( name$' )
275 init-targ 2dup targ-file$ $append
276 targ-file$ fs-open if ( name$ fd )
277 fs-close true ( name$ true )
279 2drop false ( false )
280 then ( name$ true | false )
285 : get-def-arch ( -- )
286 " device_type" root-ph get-package-property if
287 \ some older sunfires don't have device_type set
289 else ( devtype-prop$ )
290 decode-string 2swap 2drop ( devtype$ )
291 " sun4v" $= ( sun4v? )
293 if " sun4v" else " sun4u" then ( arch$ )
299 \ compatible name -or-
304 \ first try "name" in root
305 " name" root-ph get-string-prop ( name$ )
307 plat-name swap move exit ( )
310 \ next try "compatible"
311 " compatible" root-ph ( prop$ ph )
312 get-package-property invert if ( compat$ )
313 begin decode-string dup while ( compat$ name$ )
315 plat-name swap move 2drop exit ( )
317 repeat 2drop 2drop ( )
320 \ else use default name
321 arch-name$ plat-name swap move
324 \ make <pre> <file> into /platform/<pre>/<file>
325 : $plat-prepend ( file$ pre$ -- file$' )
327 targ-file$ $append ( file$ )
328 " /" targ-file$ $append
329 targ-file$ $append ( )
333 : get-boot ( -- file$ )
341 : get-kern ( -- file$ )
345 " kernel/sparcv9/unix"
349 \ if we're nested, load the kernel, else load the bootarchive
350 : get-targ ( -- file$ )
359 : try-file ( file$ -- [ fd ] error? )
361 2dup ." Loading: " type cr
363 fs-open invert ( fd false | true )
366 \ try "/platform/<plat-name>/<file>" e.g., SUNW,Sun-Blade-1000
367 \ then "/platform/<arch-name>/<file>" e.g., sun4u
368 : open-path ( file$ - fd )
369 over c@ ascii / <> if
370 2dup plat-name$ $plat-prepend ( file$ file$' )
371 try-file if ( file$ )
372 2dup arch-name$ $plat-prepend ( file$ file$' )
373 try-file if ( file$ )
378 \ copy to targ-file for 'whoami' prop
379 targ-file /buf-len erase
380 2dup targ-file swap move
381 2dup try-file if ( file$ )
392 \ -Z fsname opens specified filesystem in disk pool
395 /buf-len buffer: fs-name
396 : fs-name$ ( -- fs$ ) fs-name cscount ;
400 : open-zfs-fs ( fs$ -- )
401 2dup " open-fs" fs-ih $call-method 0= if
409 : open-zfs-fs ( fs$ -- )
412 " -Z not supported on non-zfs root" die
424 : printable? ( n -- flag ) \ true if n is a printable ascii character
425 dup bl th 7f within swap th 80 th ff between or
427 : white-space? ( n -- flag ) \ true is n is non-printable? or a blank
428 dup printable? 0= swap bl = or
431 : skip-blanks ( adr len -- adr' len' )
432 begin dup while ( adr' len' )
433 over c@ white-space? 0= if exit then
438 : skip-non-blanks ( adr len -- adr' len' )
439 begin dup while ( adr' len' )
440 over c@ white-space? if exit then
446 \ left-parse-string w/ any white space as delimeter
447 : next-str ( adr len -- adr' len' s-adr s-len )
448 2dup skip-non-blanks ( s-adr len adr' len' )
449 dup >r 2swap r> - ( adr' len' s-adr s-len )
452 \ next char or 0 if eol
453 : next-c ( adr len -- adr' len' c )
454 dup if over c@ >r str++ r> else 0 then
459 : parse-bootargs ( -- )
460 " bootargs" chosen-ph get-string-prop ( arg$ )
462 \ check for explicit kernel name
464 over c@ ascii - <> if
465 next-str ( arg$ kern$ )
466 \ use default kernel if user specific a debugger
467 2dup " kadb" $= >r ( arg$ kern$ r: kadb? )
468 2dup " kmdb" $= r> or ( arg$ kern$ debugger? )
469 invert if ( arg$ kern$ )
470 kern-file swap move ( arg$ )
472 else 2drop then ( arg$ )
478 skip-blanks dup ( arg$ len )
483 \ for "boot kadb -D kernel.foo/unix"
484 skip-blanks next-str ( arg$ file$ )
487 kern-file swap move ( arg$ )
489 else drop then ( arg$ )
490 else 2drop then ( arg$ )
493 skip-blanks next-str ( arg$ file$ )
495 boot-file swap move ( arg$ )
497 else drop then ( arg$ )
503 " /" fs-name swap move
505 " bootlst" boot-file swap move
510 skip-blanks next-str ( arg$ fs-name$ )
512 fs-name swap move ( arg$ )
514 else drop then ( arg$ )
525 : "ramdisk" ( -- dev$ ) " /ramdisk-root" ;
527 : setup-bootprops ( -- )
528 chosen-ph push-package
531 fs-type$ encode-string " fstype" property
532 fs-ih encode-int " bootfs" property
533 fs-bootprop if property then
535 fs-type$ encode-string " archive-fstype" property
536 fs-ih encode-int " archfs" property
540 "ramdisk" encode-string " bootarchive" property
542 loader-base encode-int " elfheader-address" property
543 file-sz encode-int " elfheader-length" property
544 plat-name$ encode-string " impl-arch-name" property
545 targ-file$ encode-string " whoami" property
546 fs-pkg$ encode-string " fs-package" property
553 \ load ramdisk fcode and tell the driver where
554 \ we put the ramdisk data
555 : setup-ramdisk ( base size -- )
556 /rd-fcode mem-alloc ( base size adr )
557 dup /rd-fcode fs-getrd
561 "ramdisk" str++ device-name
566 /rd-fcode mem-free ( base size )
568 "ramdisk" dev-open dup 0= if
570 then >r ( base size r: ih )
571 rd-alloc-sz ( base size alloc-sz r: ih )
572 " create" r@ $call-method ( r: ih )
585 : +elfhdr ( index -- value ) elfhdr swap ca+ ;
586 : e_machine ( -- n ) h# 12 +elfhdr w@ ;
587 : e_entry ( -- n ) h# 18 +elfhdr x@ ;
588 : e_phoff ( -- n ) h# 20 +elfhdr x@ ;
589 : e_phentsize ( -- n ) h# 36 +elfhdr w@ ;
590 : e_phnum ( -- n ) h# 38 +elfhdr w@ ;
593 : +phdr ( index -- value ) phdr swap ca+ ;
594 : p_type ( -- n ) h# 0 +phdr l@ ;
595 : p_vaddr ( -- n ) h# 10 +phdr x@ ;
596 : p_memsz ( -- n ) h# 28 +phdr x@ ;
598 : get-phdr ( filebase index -- phdr )
599 e_phentsize * e_phoff + + ( phdr )
602 \ alloc 4MB pages for kernel text/data
603 : vmem-alloc-4mb ( size virt -- base )
604 swap 4meg roundup swap
609 \ OBP doesn't allocate memory for elf
610 \ programs, it assumes they'll fit
611 \ under the default 10MB limit
612 : fix-elf-mem ( base -- )
614 e_machine d# 43 <> if drop exit then \ 64b only
617 dup i get-phdr to phdr
618 p_type pt_load = p_vaddr h# a0.0000 > and if
619 \ allocate 4MB segs for text & data
620 p_vaddr 4meg 1- and if
621 p_memsz p_vaddr vmem-alloc drop
623 p_memsz p_vaddr vmem-alloc-4mb drop
630 : load-file ( -- virt )
632 get-targ open-path ( fd )
633 loader-base over get-file if ( fd alloc-sz virt size )
634 " Boot load failed" die
636 to file-sz ( fd alloc-sz virt )
637 swap to rd-alloc-sz ( fd virt )
638 swap fs-close ( virt )
641 : setup-props ( virt -- virt )
645 dup file-sz setup-ramdisk
649 : exec-file ( virt -- )
653 is-archive? if >bootblk then ( virt' )
654 " to load-base init-program" evaluate
660 ." Halted with -H flag. " cr
666 zflag? nested? invert and if
674 \ Tadpole proms don't initialize my-self