xref: /titanic_51/usr/src/psm/stand/bootblks/common/boot.fth (revision dc5415b5ee3585f3fb9e8f0a33ea3f5926e13999)
1\
2\ CDDL HEADER START
3\
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.
7\
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.
12\
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]
18\
19\ CDDL HEADER END
20\
21\
22\ ident	"%Z%%M%	%I%	%E% SMI"
23\ Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24\ Use is subject to license terms.
25\
26
27id: %Z%%M%	%I%	%E% SMI
28purpose: boot block for OBP systems
29copyright: Copyright 2007 Sun Microsystems, Inc. All Rights Reserved
30
31
32headerless
33d# 1024 dup  *     constant  1meg
34d# 4  1meg   *     constant  4meg
35d# 32 1meg   *     constant  32meg
36
37headers
38" /"  get-package  constant  root-ph
39
400                  value     fs-ih
41false              value     nested?
420                  value     file-sz
43
44/buf-len  buffer:  boot-dev
45: boot-dev$  ( -- dev$ )  boot-dev cscount  ;
46
47: loader-base  ( -- base )
48   nested?  if
49      h# 5000.0000
50   else
51      h# 5100.0000
52   then
53;
54
55
56\
57\ methods we expect of fs reader packages
58\
59headerless
60: fs-open  ( file$ -- fd true | false )
61   " open-file" fs-ih $call-method
62;
63
64: fs-close  ( fd -- )
65   " close-file" fs-ih $call-method
66;
67
68: fs-size  ( fd -- size )
69   " size-file" fs-ih $call-method
70;
71
72: fs-read  ( adr len fd -- #read )
73   " read-file" fs-ih $call-method
74;
75
76: fs-getrd  ( adr len -- )
77   " get-rd" fs-ih $call-method
78;
79
80: fs-bootprop  ( -- propval propname true  |  false )
81   " bootprop" fs-ih $call-method
82;
83headers
84
85
86\ zfs bootblks with all headers exceeds 7.5k
87\ 'bigbootblk' allows us to load the fs reader from elsewhere
88[ifdef] bigbootblk
89
90: load-pkg  ( -- )
91   boot-dev$  2dup dev-open  ?dup 0=  if  ( dev$ )
92      open-abort
93   then  >r 2drop                         ( r: ih )
94   /fs-fcode  mem-alloc                   ( adr  r: ih )
95   dup  /fs-fcode fs-offset r@  read-disk
96   dup  1 byte-load
97   /fs-fcode  mem-free                    ( r: ih )
98   r>  dev-close
99;
100
101[else]
102
103: load-pkg  ( -- )  ;
104
105[then]
106
107
108: get-bootdev  ( -- )
109   \ first try boot archive (nested boot from ramdisk)
110   \ then try boot device (direct boot from disk)
111   " bootarchive" chosen-ph  get-package-property  if
112      " bootpath" chosen-ph  get-string-prop            ( bootpath$ )
113   else                                                 ( archiveprop$ )
114      decode-string  2swap 2drop                        ( archivepath$ )
115      true to nested?
116   then                                                 ( bootpath$ )
117   boot-dev swap  move                                  (  )
118;
119
120: mount-root  ( -- )
121   boot-dev$ fs-pkg$  $open-package to fs-ih
122   fs-ih 0=  if
123      " Can't mount root" die
124   then
125;
126
127\
128\ cheap entertainment for those watching
129\ boot progress
130\
131headerless
132create spin-data
133   ascii | c,  ascii / c,  ascii - c,  ascii \ c,
134
1350 instance variable spindex
136
137: spinner ( -- )
138   spindex @  3 and  spin-data +   ( c-adr )
139   c@ emit  (cr
140   1 spindex +!
141;
142
143: spin-on   ( -- )  ['] spinner  d# 1000  alarm  ;
144: spin-off  ( -- )  ['] spinner        0  alarm  ;
145
146headers
147\ allocate and return physical allocation size
148: vmem-alloc-prop  ( size virt -- alloc-size virt )
149   2dup  ['] vmem-alloc  catch  if            ( size virt ??? ??? )
150      2drop                                   ( size virt )
151      2dup  begin                             ( size virt len adr )
152         over 32meg  min  >r                  ( size virt len adr  r: alloc-sz )
153         r@ over  vmem-alloc                  ( size virt len adr adr  r: alloc-sz )
154         nip  r@ +                            ( size virt len adr'  r: alloc-sz )
155         swap r> -                            ( size virt adr len' )
156         swap over  0=                        ( size virt len' adr done? )
157      until                                   ( size virt len' adr )
158      2drop nip  32meg                        ( virt 32meg )
159   else                                       ( size virt virt )
160      nip nip  0                              ( virt 0 )
161   then                                       ( virt alloc-sz )
162   swap
163;
164
165\ read in file and return buffer
166\ if base==0, vmem-alloc will allocate virt
167\ NB returned size is 8k rounded since the
168\ memory allocator rounded it for us
169: get-file ( base fd -- [ alloc-sz virt size ] failed? )
170   dup >r  fs-size                         ( base size  r: fd )
171   dup rot  vmem-alloc-prop                ( size alloc-sz virt  r: fd )
172   rot  2dup tuck  r>                      ( alloc-sz virt size size virt size fd )
173   spin-on  fs-read  spin-off              ( alloc-sz virt size size size-rd )
174   <>  if                                  ( alloc-sz virt size )
175      3drop true  exit                     ( failed )
176   then
177   h# 2000  roundup                        ( alloc-sz virt size' )
178   false                                   ( alloc-sz virt size' succeeded )
179;
180
181
182false value is-elf?
183false value is-archive?
184
185: check-elf ( base -- is-elf? )
186   l@  h# 7f454c46 ( \x7fELF )  =
187;
188
189: check-fcode ( base -- is-fcode? )
190   c@ dup  h# f0 h# f3 between  swap h# fd =  or
191;
192
193: >bootblk  ( adr -- adr' )  d# 512 +  ;
194
195\ figure out what we just loaded
196: get-type  ( adr -- )
197   dup check-elf to is-elf?
198
199   \ if not nested, check for boot archive (executable after label)
200   nested? invert  if
201      >bootblk
202      dup check-fcode           ( adr is-fcode? )
203      over check-elf            ( adr is-fcode? is-elf? )
204      or  to is-archive?
205   then
206   drop
207;
208
209
210\
211\	file name routines
212\
213
214\ boot file (-F name or boot archive)
215false     value    fflag?
216/buf-len  buffer:  boot-file
217: boot-file$  ( -- file$ )  boot-file cscount  ;
218
219\ kernel name (final name or unix)
220false     value    kern?
221/buf-len  buffer:  kern-file
222: kern-file$  ( -- file$ )  kern-file cscount  ;
223
224\ platform name
225/buf-len  buffer:  plat-name
226: plat-name$  ( -- plat$ )  plat-name cscount  ;
227
228\ arch name
229/buf-len  buffer:  arch-name
230: arch-name$  ( -- arch$ )  arch-name cscount  ;
231
232\ final name after /platform massaging
233/buf-len  buffer:  targ-file
234: targ-file$  ( -- file$ )  targ-file cscount  ;
235
236headerless
237: init-targ  ( -- )
238   targ-file /buf-len erase
239   " /platform/"  targ-file swap  move
240;
241
242\ remove illegal file name chars (e.g., '/')
243: munge-name ( name$ -- name$' )
244   2dup                           ( name$ name$ )
245   begin  dup  while
246      over c@  ascii /  =  if
247         over  ascii _  swap  c!  ( name$ name$' )
248      then  str++
249   repeat  2drop                  ( name$ )
250;
251
252headers
253\ does /platform/<name> exist?
254: try-platname  ( name$ -- name$ true | false )
255   munge-name                           ( name$' )
256   init-targ  2dup targ-file$  $append
257   targ-file$ fs-open  if               ( name$ fd )
258      fs-close  true                    ( name$ true )
259   else                                 ( name$ )
260      2drop  false                      ( false )
261   then                                 ( name$ true | false )
262;
263
264\ setup arch-name
265\  sun4v  -or-  sun4u
266: get-def-arch  ( -- )
267   " device_type"  root-ph  get-package-property  if
268      \ some older sunfires don't have device_type set
269      false                             ( sun4u )
270   else                                 ( devtype-prop$ )
271      decode-string  2swap 2drop        ( devtype$ )
272      " sun4v" $=                       ( sun4v? )
273   then                                 ( sun4v? )
274   if  " sun4v"  else  " sun4u"  then   ( arch$ )
275   arch-name swap  move
276;
277
278\ setup plat-name
279\  platform name  -or-
280\  compatible name  -or-
281\  default name
282: get-arch  ( -- )
283   get-def-arch
284
285   \ first try "name" in root
286   " name"  root-ph  get-string-prop           ( name$ )
287   try-platname  if
288      plat-name swap  move  exit               (  )
289   then                                        (  )
290
291   \ next try "compatible"
292   " compatible"  root-ph                      ( prop$ ph )
293   get-package-property  invert  if            ( compat$ )
294      begin  decode-string dup  while          ( compat$ name$ )
295         try-platname  if
296            plat-name swap  move  2drop  exit  (  )
297         then                                  ( compat$ )
298      repeat  2drop 2drop                      (  )
299   then                                        (  )
300
301   \ else use default name
302   arch-name$  plat-name swap  move
303;
304
305\ make <pre> <file> into /platform/<pre>/<file>
306: $plat-prepend  ( file$ pre$ -- file$' )
307   init-targ
308   targ-file$  $append                 ( file$ )
309   " /" targ-file$  $append
310   targ-file$  $append                 (  )
311   targ-file$                          ( new$ )
312;
313
314: get-boot  ( -- file$ )
315   fflag?  if
316      boot-file$
317   else
318      " boot_archive"
319   then
320;
321
322: get-kern  ( -- file$ )
323   kern?  if
324      kern-file$
325   else
326      " kernel/sparcv9/unix"
327   then
328;
329
330\ if we're nested, load the kernel, else load the bootarchive
331: get-targ  ( -- file$ )
332   nested?  if
333      get-kern
334   else
335      get-boot
336   then
337;
338
339
340: try-file  ( file$ -- [ fd ] error? )
341   diagnostic-mode?  if
342      2dup ." Loading: " type cr
343   then
344   fs-open  invert         ( fd false | true )
345;
346
347\  try "/platform/<plat-name>/<file>"  e.g., SUNW,Sun-Blade-1000
348\  then "/platform/<arch-name>/<file>"  e.g., sun4u
349: open-path  ( file$ - fd )
350   over c@ ascii /  <>  if
351      2dup  plat-name$  $plat-prepend      ( file$ file$' )
352      try-file  if                         ( file$ )
353         2dup  arch-name$  $plat-prepend   ( file$ file$' )
354         try-file  if                      ( file$ )
355           open-abort
356         then                              ( file$ fd )
357      then                                 ( file$ fd )
358   else                                    ( file$ )
359      \ copy to targ-file for 'whoami' prop
360      targ-file /buf-len  erase
361      2dup targ-file swap  move
362      2dup  try-file  if                   ( file$ )
363        open-abort
364      then                                 ( file$ fd )
365   then                                    ( file$ fd )
366   -rot 2drop                              ( fd )
367;
368
369
370false  value  lflag?
371
372\ ZFS support
373\ -Z fsname  opens specified filesystem in disk pool
374
375false     value    zflag?
376/buf-len  buffer:  fs-name
377: fs-name$  ( -- fs$ )  fs-name cscount  ;
378
379[ifdef] zfs
380
381: open-zfs-fs  ( fs$ -- )
382   2dup  " open-fs" fs-ih $call-method  0=  if
383      open-abort
384   then
385   2drop                     (  )
386;
387
388[else]
389
390: open-zfs-fs ( fs$ -- )
391   \ ignore on -L
392   lflag? invert  if
393      " -Z not supported on non-zfs root"  die
394   then
395;
396
397[then]
398
399
400\
401\	arg parsing
402\
403
404headerless
405: printable?  ( n -- flag ) \ true if n is a printable ascii character
406   dup bl th 7f within  swap  th 80  th ff  between  or
407;
408: white-space? ( n -- flag ) \ true is n is non-printable? or a blank
409   dup printable? 0=  swap  bl =  or
410;
411
412: skip-blanks  ( adr len -- adr' len' )
413   begin  dup  while   ( adr' len' )
414      over c@  white-space? 0=  if  exit  then
415      str++
416   repeat
417;
418
419: skip-non-blanks  ( adr len -- adr' len' )
420   begin  dup  while   ( adr' len' )
421      over c@  white-space?  if  exit  then
422      str++
423   repeat
424;
425
426headers
427\ left-parse-string w/ any white space as delimeter
428: next-str  ( adr len -- adr' len' s-adr s-len )
429   2dup  skip-non-blanks       ( s-adr len adr' len' )
430   dup >r  2swap  r> -         ( adr' len' s-adr s-len )
431;
432
433: next-c  ( adr len -- adr' len' c )
434   over c@ >r  str++  r>
435;
436
437false value halt?
438
439: parse-bootargs  ( -- )
440   " bootargs" chosen-ph  get-string-prop  ( arg$ )
441
442   \ check for explicit kernel name
443   skip-blanks  dup  if
444      over c@  ascii -  <>  if
445         next-str                          ( arg$ kern$ )
446         \ use default kernel if user specific a debugger
447         2dup  " kadb"  $=  >r             ( arg$ kern$  r: kadb? )
448         2dup  " kmdb"  $=  r>  or         ( arg$ kern$ debugger? )
449         invert  if                        ( arg$ kern$ )
450            kern-file swap  move           ( arg$ )
451            true to kern?
452         else  2drop  then                 ( arg$ )
453      then
454   then
455
456   \ process args
457   begin
458      skip-blanks  dup                     ( arg$ len )
459   while
460      next-c  ascii -  =  if
461         next-c  case
462            ascii D  of
463               \ for "boot kadb -D kernel.foo/unix"
464               skip-blanks  next-str       ( arg$ file$ )
465               kern? invert  if
466                  ?dup  if
467                     kern-file swap  move  ( arg$ )
468                     true to kern?
469                  else  drop  then         ( arg$ )
470               else  2drop  then           ( arg$ )
471            endof
472            ascii F  of
473               skip-blanks  next-str       ( arg$ file$ )
474               ?dup  if
475                  boot-file swap  move     ( arg$ )
476                  true to fflag?
477               else  drop  then            ( arg$ )
478            endof
479            ascii H  of
480               true to halt?
481            endof
482            ascii L  of
483               " /" fs-name swap  move
484               true to zflag?
485               " bootlst" boot-file swap  move
486               true to fflag?
487               true to lflag?
488            endof
489            ascii Z  of
490               skip-blanks  next-str       ( arg$ fs-name$ )
491               ?dup  if
492                  fs-name swap  move       ( arg$ )
493                  true to zflag?
494               else  drop  then            ( arg$ )
495            endof
496         endcase
497      then
498   repeat
499   2drop                                   (  )
500;
501
502
5030 value rd-alloc-sz
504
505: "ramdisk"  ( -- dev$ )  " /ramdisk-root"  ;
506
507: setup-bootprops  ( -- )
508   chosen-ph  push-package
509
510   nested? invert  if
511      fs-type$ encode-string    " fstype"             property
512      fs-ih encode-int          " bootfs"             property
513      fs-bootprop  if  property  then
514   else
515      fs-type$ encode-string    " archive-fstype"     property
516      fs-ih encode-int          " archfs"             property
517   then
518
519   is-archive?  if
520      "ramdisk" encode-string   " bootarchive"        property
521   else
522      loader-base encode-int    " elfheader-address"  property
523      file-sz encode-int        " elfheader-length"   property
524      plat-name$ encode-string  " impl-arch-name"     property
525      targ-file$ encode-string  " whoami"             property
526      fs-pkg$ encode-string     " fs-package"         property
527   then
528
529   pop-package
530;
531
532
533\ load ramdisk fcode and tell the driver where
534\ we put the ramdisk data
535: setup-ramdisk  ( base size -- )
536   /rd-fcode mem-alloc                ( base size adr )
537   dup /rd-fcode  fs-getrd
538
539   root-ph  push-package
540   new-device
541      "ramdisk" str++  device-name
542      dup 1  byte-load
543   finish-device
544   pop-package
545
546   /rd-fcode mem-free              ( base size )
547
548   "ramdisk"  dev-open  dup 0=  if
549      "ramdisk" open-abort
550   then  >r                        ( base size  r: ih )
551   rd-alloc-sz                     ( base size alloc-sz  r: ih )
552   " create"  r@ $call-method      ( r: ih )
553   r> dev-close                    (  )
554;
555
556
557\
558\	ELF parsing
559\
560
561headerless
5620 value elfhdr
5630 value phdr
564
565: +elfhdr	( index -- value )  elfhdr swap ca+ ;
566: e_machine     ( -- n )  h# 12 +elfhdr w@ ;
567: e_entry	( -- n )  h# 18 +elfhdr x@ ;
568: e_phoff	( -- n )  h# 20 +elfhdr x@ ;
569: e_phentsize	( -- n )  h# 36 +elfhdr w@ ;
570: e_phnum	( -- n )  h# 38 +elfhdr w@ ;
571
5721 constant pt_load
573: +phdr		( index -- value )  phdr swap ca+ ;
574: p_type	( -- n )  h#  0 +phdr l@ ;
575: p_vaddr	( -- n )  h# 10 +phdr x@ ;
576: p_memsz	( -- n )  h# 28 +phdr x@ ;
577
578: get-phdr ( filebase index -- phdr )
579   e_phentsize *  e_phoff +  +    ( phdr )
580;
581
582\ alloc 4MB pages for kernel text/data
583: vmem-alloc-4mb  ( size virt -- base )
584   swap  4meg roundup  swap
585   4meg (mem-alloc)
586;
587
588headers
589\ OBP doesn't allocate memory for elf
590\ programs, it assumes they'll fit
591\ under the default 10MB limit
592: fix-elf-mem  ( base -- )
593   dup to elfhdr
594   e_machine  d# 43  <>  if  drop exit  then       \ 64b only
595
596   e_phnum 0  ?do
597      dup i get-phdr  to phdr
598      p_type pt_load =  p_vaddr h# a0.0000 >  and  if
599         \ allocate 4MB segs for text & data
600         p_vaddr  4meg 1-  and  if
601            p_memsz p_vaddr  vmem-alloc  drop
602         else
603            p_memsz p_vaddr  vmem-alloc-4mb  drop
604         then
605      then
606   loop  drop                   (  )
607;
608
609
610: load-file  ( -- virt )
611   get-arch
612   get-targ  open-path              ( fd )
613   loader-base over  get-file  if   ( fd alloc-sz virt size )
614      " Boot load failed" die
615   then
616   to file-sz                       ( fd alloc-sz virt )
617   swap  to rd-alloc-sz             ( fd virt )
618   swap  fs-close                   ( virt )
619;
620
621: setup-props  ( virt -- virt )
622   dup get-type
623   setup-bootprops
624   is-archive?  if
625      dup file-sz  setup-ramdisk
626   then
627;
628
629: exec-file  ( virt -- )
630   is-elf?  if
631      dup  fix-elf-mem
632   then
633   is-archive?  if  >bootblk  then          ( virt' )
634   " to load-base init-program"  evaluate
635;
636
637: do-boot ( -- )
638   parse-bootargs
639   halt?  if
640      ." Halted with -H flag. " cr
641      exit
642   then
643   get-bootdev
644   load-pkg
645   mount-root
646   zflag?  nested? invert  and  if
647      fs-name$  open-zfs-fs
648   then
649   load-file                        ( virt )
650   setup-props
651   exec-file                        (  )
652;
653
654\ Tadpole proms don't initialize my-self
6550 to my-self
656
657do-boot
658