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