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