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