xref: /netbsd-src/sys/arch/sparc/stand/bootblk/bootblk.fth (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1\	$NetBSD: bootblk.fth,v 1.13 2010/06/24 00:54:12 eeh Exp $
2\
3\	IEEE 1275 Open Firmware Boot Block
4\
5\	Parses disklabel and UFS and loads the file called `ofwboot'
6\
7\
8\	Copyright (c) 1998-2010 Eduardo Horvath.
9\	All rights reserved.
10\
11\	Redistribution and use in source and binary forms, with or without
12\	modification, are permitted provided that the following conditions
13\	are met:
14\	1. Redistributions of source code must retain the above copyright
15\	   notice, this list of conditions and the following disclaimer.
16\	2. Redistributions in binary form must reproduce the above copyright
17\	   notice, this list of conditions and the following disclaimer in the
18\	   documentation and/or other materials provided with the distribution.
19\
20\	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21\	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22\	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23\	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24\	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25\	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26\	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27\	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28\	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29\	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30\
31
32offset16
33hex
34headers
35
36false value boot-debug?
37
38: KB d# 1024 * ;
39
40\
41\ First some housekeeping:  Open /chosen and set up vectors into
42\	client-services
43
44" /chosen" find-package 0=  if ." Cannot find /chosen" 0 then
45constant chosen-phandle
46
47" /openprom/client-services" find-package 0=  if
48	." Cannot find client-services" cr abort
49then constant cif-phandle
50
51defer cif-claim ( align size virt -- base )
52defer cif-release ( size virt -- )
53defer cif-open ( cstr -- ihandle|0 )
54defer cif-close ( ihandle -- )
55defer cif-read ( len adr ihandle -- #read )
56defer cif-seek ( low high ihandle -- -1|0|1 )
57\ defer cif-peer ( phandle -- phandle )
58\ defer cif-getprop ( len adr cstr phandle -- )
59
60: find-cif-method ( method len -- xf )
61   cif-phandle find-method drop
62;
63
64" claim" find-cif-method  to  cif-claim
65" open" find-cif-method  to  cif-open
66" close" find-cif-method  to  cif-close
67" read" find-cif-method  to  cif-read
68" seek" find-cif-method  to  cif-seek
69
70: twiddle ( -- ) ." ." ; \ Need to do this right.  Just spit out periods for now.
71
72\
73\ Support routines
74\
75
76\ 64-bit math support
77
78here h# ffff over l! <w@ constant little-endian?
79: ul>d ( l -- d.lo d.hi )	0 ;
80: l>d ( l -- d.lo d.hi )	dup 0<  if  -1  else  0  then ;
81: d>l ( d.lo d.hi -- l )	drop ;
82: d@ ( addr -- d.lo d.hi )	dup l@ swap la1+ l@ little-endian? invert  if  swap  then ;
83: d! ( d.lo d.hi addr -- )
84   little-endian? invert  if  -rot swap rot  then  tuck la1+ l! l! ;
85: d-and ( d1 d2 -- d1-and-d2 )  rot and -rot and swap ;
86: d*u ( d1 u -- d2 )		tuck um* drop -rot um* rot + ;
87: d<< ( d1 n -- d1<<n )	\ Hope this works
88   ?dup  if  \ Shifting by 0 doesn't appear to work properly.
89      tuck <<			( d.lo n d.hi' )
90      -rot 2dup <<		( d.hi' d.lo n d.lo' )
91      -rot d# 32 swap - >>	( d.hi' d.lo' lo.hi )
92      rot +
93   then
94;
95: d>> ( d1 n -- d1>>n )	\ Hope this works
96   ?dup  if  \ Shifting by 0 doesn't appear to work properly.
97      rot over >>	-rot	( d.lo' d.hi n )
98      2dup >> -rot		( d.lo' d.hi' d.hi n )
99      d# 32 swap - << rot + swap
100   then
101;
102: d> ( d1 d2 -- d1>d2? )
103   rot swap 2dup = if
104      2drop > exit
105   then
106   > nip nip
107;
108: d>= ( d1 d2 -- d1>=d2? )
109   rot swap 2dup =  if
110      2drop >= exit
111   then
112   >= nip nip
113;
114: d< ( d1 d2 -- d1<d2? )	d>= invert ;
115: d= ( d1 d2 -- d1=d2? )	rot = -rot = and ;
116: d<> ( d1 d2 -- d1<>d2? )	d= invert ;
117
118
119\ String support
120
121: strcmp ( s1 l1 s2 l2 -- true:false )
122   rot tuck <>  if  3drop false exit  then
123   comp 0=
124;
125
126\ Move string into buffer
127
128: strmov ( s1 l1 d -- d l1 )
129   dup 2over swap -rot		( s1 l1 d s1 d l1 )
130   move				( s1 l1 d )
131   rot drop swap
132;
133
134\ Move s1 on the end of s2 and return the result
135
136: strcat ( s1 l1 s2 l2 -- d tot )
137   2over swap 				( s1 l1 s2 l2 l1 s1 )
138   2over + rot				( s1 l1 s2 l2 s1 d l1 )
139   move rot + 				( s1 s2 len )
140   rot drop				( s2 len )
141;
142
143: strchr ( s1 l1 c -- s2 l2 )
144   begin
145      dup 2over 0= if			( s1 l1 c c s1  )
146         2drop drop exit then
147      c@ = if				( s1 l1 c )
148         drop exit then
149      -rot /c - swap ca1+		( c l2 s2 )
150     swap rot
151  again
152;
153
154
155: cstr ( ptr -- str len )
156   dup
157   begin dup c@ 0<>  while + repeat
158   over -
159;
160
161\
162\ BSD UFS parameters
163\
164
165fload	ffs.fth.h
166fload   lfs.fth.h
167
168sbsize buffer: sb-buf
169-1 value boot-ihandle
170dev_bsize value bsize
1710 value raid-offset	\ Offset if it's a raid-frame partition
172
173: strategy ( addr size db.lo db.hi -- nread )
174    raid-offset l>d d+			( addr size db.lo' db.hi' )
175    bsize d*u				( addr size sector.lo sector.hi )
176    " seek" boot-ihandle $call-method -1 = if
177	." strategy: Seek failed" cr
178	abort
179    then				( addr size )
180    " read" boot-ihandle $call-method
181;
182
183
184\
185\ Multi-FS support
186\
187\ XXX Maybe the different filesystems should be segregated into separate files
188\ XXX that are individually fload-ed.
189\
190
191defer fs-size
192defer di-size
193defer di-mode
194defer /dino
195defer cgstart
196defer di-db@
197defer di-ib@
198defer ib-ib@
199defer fs-bsize
200defer fsbtodb
201defer blksize
202defer lblkno
203defer blkoff
204defer read-inode
205\ LFS ifile
206defer /ifile
207defer if_daddr
208
209\
210\ FFS Cylinder group macros
211\
212
213: cgdmin ( cg fs -- d-1st-data-block )	dup fs_dblkno l@ l>d 2swap cgstart d+ ;
214: cgimin ( cg fs -- d-inode-block )	dup fs_iblkno l@ l>d 2swap cgstart d+ ;
215: cgsblock ( cg fs -- d-super-block )	dup fs_sblkno l@ l>d 2swap cgstart d+ ;
216: cgstod ( cg fs -- d-cg-block )	dup fs_cblkno l@ l>d 2swap cgstart d+ ;
217
218\
219\ FFS Block and frag position macros
220\
221
222: ffs-blkoff ( pos.lo pos.hi fs -- off.lo off.hi )	fs_qbmask d@ d-and ;
223\ : ffs-fragoff ( pos.lo pos.hi fs -- off.lo off.hi )	fs_qfmask d@ d-and ;
224\ : ffs-lblktosize ( blk fs -- off.lo off.hi )		0 fs_bshift l@ d<< ;
225: ffs-lblkno ( pos.lo pos.hi fs -- off.lo off.hi )	fs_bshift l@ d>> ;
226: ffs-numfrags ( pos.lo pos.hi fs -- off.lo off.hi )	fs_fshift l@ d>> ;
227: ffs-blkroundup ( pos.lo pos.hi fs -- off.lo off.hi )
228    >r r@ fs_qbmask d@ d+ r> fs_bmask l@ l>d d-and
229;
230: ffs-fragroundup ( pos.lo pos.hi fs -- off.lo off.hi )
231    >r r@ fs_qfmask d@ d+ r> fs_fmask l@ l>d d-and
232;
233: ffs-fragstoblks ( pos.lo pos.hi fs -- off.lo off.hi )	fs_fragshift l@ d>> ;
234: ffs-blkstofrags ( blk fs -- frag )			fs_fragshift l@ << ;
235\ : ffs-fragnum ( fsb fs -- off )			fs_frag l@ 1- and ;
236\ : ffs-blknum ( fsb fs -- off )			fs_frag l@ 1- not and ;
237: ffs-dblksize ( lbn.lo lbn.hi inodep fs -- size )
238   >r -rot 2dup ndaddr l>d d>		( inop d-lbn >ndaddr? )
239   -rot 1 0 d+				( inop >ndaddr? d-lbn+1 )
240   r@ fs_bshift l@ d<<			( inop >ndaddr? d-lbn+1<<bshift )
241   2swap >r di-size d@			( d-lbn+1<<bshift d-size )
242   2swap 2over d< r> or  if		( d-size )
243	2drop r> fs-bsize l@ exit
244    then
245    r@ ffs-blkoff			( size.lo size.hi )
246    r> ffs-fragroundup d>l		( size )
247;
248
249: ino-to-cg ( ino fs -- cg )		fs_ipg l@ / ;
250: ino-to-fsbo ( ino fs -- fsb0 )	fs_inopb l@ mod ;
251: ino-to-fsba ( ino fs -- ba.lo ba.hi )	\ Need to remove the stupid stack diags someday
252   2dup 				( ino fs ino fs )
253   ino-to-cg				( ino fs cg )
254   over					( ino fs cg fs )
255   cgimin				( ino fs inode-blk.lo inode-blk.hi )
256   2swap				( d-inode-blk ino fs )
257   tuck 				( d-inode-blk fs ino fs )
258   fs_ipg l@ 				( d-inode-blk fs ino ipg )
259   mod					( d-inode-blk fs mod )
260   swap					( d-inode-blk mod fs )
261   dup 					( d-inode-blk mod fs fs )
262   fs_inopb l@ 				( d-inode-blk mod fs inopb )
263   rot 					( d-inode-blk fs inopb mod )
264   swap					( d-inode-blk fs mod inopb )
265   /					( d-inode-blk fs div )
266   swap					( d-inode-blk div fs )
267   ffs-blkstofrags			( d-inode-blk frag )
268   0 d+
269;
270: ffs-fsbtodb ( fsb.lo fsb.hi fs -- db.lo db.hi )
271    fs_fsbtodb l@ d<<
272;
273
274
275\
276\ LFS suff
277\
278: lfs-blkoff ( pos.lo pos.hi fs -- off.lo off.hi )	lfs_bmask d@ d-and ;
279\ : lfs-fragoff ( pos.lo pos.hi fs -- off.lo off.hi )	lfs_ffmask d@ d-and ;
280\ : lfs-lblktosize ( blk fs -- off.lo off.hi )		0 lfs_bshift l@ d<< ;
281: lfs-lblkno ( pos.lo pos.hi fs -- off.lo off.hi )	lfs_bshift l@ d>> ;
282: lfs-numfrags ( pos.lo pos.hi fs -- off.lo off.hi )	lfs_ffshift l@ d>> ;
283: lfs-roundup ( pos.lo pos.hi mask.lo mask.hi )
284   2swap 2over d+ 2swap			( d-pos* d-mask )
285   invert swap invert swap d-and
286;
287: lfs-blkroundup ( pos.lo pos.hi fs -- off.lo off.hi )	lfs_bmask d@ lfs-roundup ;
288: lfs-fragroundup ( pos.lo pos.hi fs -- off.lo off.hi )	lfs_ffmask d@ lfs-roundup ;
289: lfs-fragstoblks ( pos.lo pos.hi fs -- off.lo off.hi )	lfs_fbshift l@ d>> ;
290: lfs-dblksize ( lbn.lo lbn.hi inodep fs -- size )
291   >r -rot 2dup ndaddr l>d d>		( inop d-lbn >ndaddr? )
292   -rot 1 0 d+				( inop >ndaddr? d-lbn+1 )
293   r@ fs_bshift l@ d<<			( inop >ndaddr? d-lbn+1<<bshift )
294   2swap >r di-size d@			( d-lbn+1<<bshift d-size )
295   2swap 2over d< r> or  if		( d-size )
296      2drop r> fs-bsize l@ exit
297   then
298   r@ lfs-blkoff			( size.lo size.hi )
299   r> lfs-fragroundup d>l		( size )
300;
301: lfs-fsbtodb ( fsb.lo fsb.hi fs -- db.lo db.hi )
302    lfs_fsbtodb l@ d<<
303;
304
305\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
306\
307\ The rest of the multi-filesystem stuff
308\
309\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
310
311\
312\ FFS v1
313\
314: di-db-v1@ ( indx dinode -- db.lo db.hi )	di1_db swap la+ l@ l>d ;
315: di-ib-v1@ ( indx dinode -- db.lo db.hi )	di1_ib swap la+ l@ l>d ;
316: ib-ib-v1@ ( indx iblk -- db.lo db.hi )	swap la+ l@ l>d ;
317
318: cgbase ( cg fs -- daddr.lo daddr.hi ) fs_fpg l@ um* ;
319: cgstart-ufs1 ( cg fs -- cgstart )
320    2dup fs_old_cgmask l@ invert and		( cg fs stuff )
321    over fs_old_cgoffset l@ um*			( cg fs off.lo off.hi )
322    2swap cgbase d+				( off.lo off.hi )
323;
324
325\
326\ FFS v2
327\
328
329: di-db-v2@ ( indx dinode -- db.lo db.hi )	di2_db swap 2* la+ d@ ;
330: di-ib-v2@ ( indx dinode -- db.lo db.hi )	di2_ib swap 2* la+ d@ ;
331: ib-ib-v2@ ( indx iblk -- db.lo db.hi )	2* la+ d@ ;
332
333\
334\ LFS v1
335\
336
337
338\
339\ File stuff
340\
341
342niaddr /w* constant narraysize
343
344\ Assume UFS2 dinodes are always biger than UFS1
345ufs2_dinode_SIZEOF buffer: cur-inode
3460 value indir-block
347create indir-addr -1 , -1 ,
348
349\
350\ Translate a fileblock to a disk block
351\
352\ We don't do triple indirect blocks.
353\
354
355\ Get the disk address from a single indirect block
356: ib@ ( indx indir.lo indir.hi -- db.lo db.hi )
357    2dup indir-addr d@ d<>  if		( indx indir.hi indir.lo )
358	indir-addr d!			( indx )
359	indir-block 			( indx indir-block )
360	sb-buf fs-bsize l@		( indx indir-block fs fs-bsize )
361	indir-addr d@ sb-buf		( indx indir-block fs-bsize indiraddr fs )
362	fsbtodb 			( indx indir-block fs-bsize db.lo db.hi )
363	strategy 0			( indx nread 0 ) \ Really should check return value
364    then
365    2drop				( indx )
366    indir-block ib-ib@
367;
368
369
370: block-map ( fileblock -- diskblock.lo diskblock.hi )
371    \ Direct block?
372    dup ndaddr <  if			( fileblock )
373	cur-inode di-db@ exit		( diskblock.lo diskblock.hi )
374    then 				( fileblock )
375    ndaddr -				( fileblock' )
376    \ Now we need to check the indirect block
377    dup sb-buf fs_nindir l@ <  if	( fileblock' )
378	0 cur-inode di-ib@		( fileblock' indir.lo indir.hi )
379	ib@ exit			( db.lo db.hi )
380   then
381   dup sb-buf fs_nindir -		( fileblock'' )
382   \ Now try 2nd level indirect block -- just read twice
383   dup sb-buf fs_nindir l@ dup * >= if	( fileblock'' )
384       ." block-map: exceeded max file size" cr
385       abort
386   then
387
388   1 cur-inode di-ib@		( fileblock'' ib.lo ib.hi )
389
390   \ Get 1st indirect block and find the 2nd indirect block
391   rot dup sb-buf fs_nindir u/mod	( ib2.lo ib2.hi indx2 indx1 )
392   2swap ib@			( indx2 ib2.lo ib2.hi )
393
394   \ Get 2nd indirect block and find our diskblock
395   ib@				( db.lo db.hi )
396;
397
398\
399\ Read file into internal buffer and return pointer and len
400\
401
4020 value cur-block			\ allocated dynamically in ufs-open
4030 value cur-blocksize			\ size allocated  to  cur-block
404create cur-blockno -1 l, -1 l,		\ Current disk block.
405-1 value file-blockno			\ Current file block no.
4060 value file-offset			\ Current file offset, max 4GB.
407
408: buf-read-file ( fs -- buf len )
409    >r file-offset			( seek )
410    dup l>d r@ lblkno drop		( seek blk )
411    dup l>d cur-inode r@ blksize	( seek blk blksize )
412    over file-blockno <> if		( seek blk blksize )
413	over  to  file-blockno
414	swap block-map			( seek blksize fsblk.lo fsblk.hi )
415	2dup or 0=  if			( seek blksize fsblk.lo fsblk.hi )
416	    \ Clear out curblock  XXX Why? Idunno.
417	    2drop dup
418	    cur-block swap erase	( seek blksize )
419	    boot-debug?  if ." buf-read-file reading block 0" cr then
420	    -1 l>d			\ Invalid disk block
421	else
422	    \ Call strategy to load the correct block.
423	    r@ fsbtodb			( seek blksize dblk.lo dblk.hi )
424	    rot >r cur-block r@ 2over	( seek addr size db.lo db.hi )
425	    strategy r@	<>  if  ." buf-read-file: short read." cr abort  then
426	    r> -rot			( seek size db.lo db.hi )
427	then
428	\ Save the new current disk block number
429	cur-blockno d!			( seek size )
430   else
431      nip				( seek size )
432   then
433   \ Now figure out how much we have in the buffer.
434   swap l>d r> blkoff			( size off.lo off.hi )
435   d>l cur-block over +			( size off buf )
436   -rot -				( buf siz )
437;
438
439\
440\ Read inode into cur-inode -- uses cur-block
441\
442
443: read-inode-ffs ( inode fs -- )
444    twiddle
445
446    >r dup r@ ino-to-fsba		( ino fsblk.lo fsblck.hi )
447    r@ fsbtodb				( ino dblk.lo dblk.hi )
448    2dup cur-blockno d@ d<>  if		( ino dblk.lo dblk.hi )
449	\ We need  to  read the block
450	cur-block r@ fs-bsize l@	( ino dblk.lo dblk.hi addr size )
451	>r r@ 2over strategy r> <> if	( ino dblk.lo dblk.hi )
452	    ." read-inode - residual" cr abort
453	then
454	2dup cur-blockno d!		( ino dblk.lo dblk.hi )
455    then 2drop				( ino )
456
457    r> ino-to-fsbo /dino *		( off )
458    cur-block + cur-inode /dino move	( )
459;
460
461: find-inode-sector ( ino fs -- d-dblkno true | false )
462   >r r@ lfs_ifile l@ r@  read-inode	( ino )
463
464   r@ lfs_ifpb l@ u/mod			( rem q )
465
466   r@ lfs_cleansz l@ +
467   r@ lfs_segtabsz l@ +			( rem blkno )
468
469   r@ fs-bsize l@ um* rot /ifile um* d+	( dseekp )
470
471   drop  to  file-offset r@ buf-read-file	( buf len )
472
473   /ifile <  if  r> 2drop false exit  then	( buf )
474
475   if_daddr l@ l>d r> fsbtodb		( daddr )
476   2dup lfs_unused_daddr l>d d=  if  2drop false  then
477   true
478;
479
480: read-inode-lfs ( inode fs -- )
481   twiddle
482
483   >r dup r@ lfs_ifile l@ =  if		( ino  r: fs )
484      r@ lfs_idaddr l@ l>d		( ino d-idaddr )
485      r@ fsbtodb			( ino d-db )
486   else
487      dup r@ find-inode-sector 0= abort" Could not find inode sector!"
488   then					( ino d-db )
489
490    2dup cur-blockno d@ d<>  if		( ino dblk.lo dblk.hi )
491	\ We need to read the block
492	cur-block r@ fs-bsize l@	( ino dblk.lo dblk.hi addr size )
493	>r r@ 2over strategy r> <> if	( ino dblk.lo dblk.hi )
494	    ." read-inode - residual" cr abort
495	then
496	2dup cur-blockno d!		( ino dblk.lo dblk.hi )
497    then  2drop				( ino )
498
499    r@ lfs_inopb l@			( ino cnt )
500    swap cur-block  begin		( cnt ino p )
501       tuck di_inumber l@ over <>	( cnt p ino !found? )
502    while				( cnt p ino )
503	  rot 1- ?dup 0=  abort" Could not find inode!"
504	  rot /dino + swap -rot		( cnt ino p )
505    repeat  swap			( cnt ino p )
506
507    cur-inode /dino move		( cnt ino )
508
509    r> 3drop
510;
511
512\ Identify inode type
513
514: is-dir? ( ufs1_dinode -- is-dir? )		di-mode w@ ifmt and ifdir = ;
515: is-symlink? ( ufs1_dinode -- is-symlink? )	di-mode w@ ifmt and iflnk = ;
516
517\
518\ Multi-FS initialiation.
519\
520\ It's way down here so all the fs-specific routines have already been defined.
521\
522
523: init-ffs-common ( -- )
524   ' fs_SIZEOF  to  fs-size
525   ' fs_bsize  to  fs-bsize
526   ' ffs-dblksize  to  blksize
527   ' read-inode-ffs  to  read-inode
528   ' ffs-fsbtodb  to  fsbtodb
529   ' ffs-lblkno  to  lblkno
530   ' ffs-blkoff  to   blkoff
531;
532
533
534: ffs-oldcompat ( -- )
535   \ Make sure old ffs values in sb-buf are sane
536   sb-buf fs_old_npsect dup l@ sb-buf fs_old_nsect l@ max swap l!
537   sb-buf fs_old_interleave dup l@ 1 max swap l!
538   sb-buf fs_old_postblformat l@ fs_42postblfmt =  if
539      8 sb-buf fs_old_nrpos l!
540   then
541   sb-buf fs_old_inodefmt l@ fs_44inodefmt <  if
542      sb-buf fs-bsize l@
543      dup ndaddr um* 1 d- sb-buf fs_maxfilesize d!
544      niaddr 0  ?do
545	 sb-buf fs_nindir l@ * dup	( sizebp sizebp )
546	 sb-buf fs_maxfilesize dup d@ ( sizebp sizebp *mxfs mxfs.lo mxfs.hi )
547	 2over drop l>d d+ 2swap d!	( sizebp )
548      loop  drop 			( )
549      sb-buf dup fs_bmask l@ invert l>d rot fs_qbmask d!
550      sb-buf dup fs_fmask l@ invert l>d rot fs_qfmask d!
551   then
552;
553
554
555: init-ffs-v1 ( -- )
556   boot-debug?  if  ." FFS v1" cr  then
557   init-ffs-common
558   ' di1_size  to  di-size
559   ' di1_mode  to  di-mode
560   ' ufs1_dinode_SIZEOF  to  /dino
561   ' cgstart-ufs1  to  cgstart
562   ' di-db-v1@  to  di-db@
563   ' di-ib-v1@  to  di-ib@
564   ' ib-ib-v1@  to  ib-ib@
565   ffs-oldcompat
566;
567
568: init-ffs-v2 ( -- )
569   boot-debug?  if  ." FFS v2" cr  then
570   init-ffs-common
571   ' di2_size  to  di-size
572   ' di2_mode  to  di-mode
573   ' ufs2_dinode_SIZEOF  to  /dino
574   ' cgbase  to  cgstart
575   ' di-db-v2@  to  di-db@
576   ' di-ib-v2@  to  di-ib@
577   ' ib-ib-v2@  to  ib-ib@
578;
579
580: init-lfs-common ( -- )
581   ' dlfs_SIZEOF  to  fs-size
582   ' di1_size  to  di-size
583   ' di1_mode  to  di-mode
584   ' ufs1_dinode_SIZEOF  to  /dino
585   ' cgbase  to  cgstart
586   ' di-db-v1@  to  di-db@
587   ' di-ib-v1@  to  di-ib@
588   ' ib-ib-v1@  to  ib-ib@
589   ' lfs-dblksize  to  blksize
590   ' read-inode-lfs  to  read-inode
591   ' lfs-fsbtodb  to  fsbtodb
592   ' lfs-lblkno  to  lblkno
593   ' lfs-blkoff  to  blkoff
594;
595
596: init-lfs-v1 ( -- )
597   boot-debug?  if  ." LFS v1" cr  then
598   init-lfs-common
599   ' lfs_ibsize  to  fs-bsize
600   ' ifile_v1_SIZEOF  to  /ifile
601   ' if1_daddr  to  if_daddr
602;
603
604: init-lfs-v2 ( -- )
605   boot-debug?  if  ." LFS v2" cr  then
606   init-lfs-common
607   ' lfs_bsize  to  fs-bsize
608   ' ifile_SIZEOF  to  /ifile
609   ' if2_daddr  to  if_daddr
610;
611
612
613: fs-magic? ( sb -- is-ufs? )
614   \ The LFS magic is the first word in the superblock
615   dup lfs_magic l@ lfs_magic_value =  if
616      dup lfs_version l@  case		( sb sel )
617	 1  of  init-lfs-v1 drop true exit  endof
618	 2  of  init-lfs-v2 drop true exit  endof
619	 ." Invalid LFS version."  \ Try FFS.
620      endcase
621   then					( sb )
622   \ The FFS magic is at the end of the superblock
623   \ XXX we should check to make sure this is not an alternate SB.
624   fs_magic l@  case
625      fs1_magic_value  of  init-ffs-v1 true  endof
626      fs2_magic_value  of  init-ffs-v2 true  endof
627      false swap	\ Return false
628   endcase
629;
630
631
632
633\
634\ Hunt for directory entry:
635\
636\ repeat
637\    load a buffer
638\    while entries do
639\       if entry == name return
640\       next entry
641\ until no buffers
642\
643
644: search-dir-block ( str len buf len -- ino | 0 )
645    2dup + nip				( str len buf bufend )
646    swap 2swap rot			( bufend str len direct )
647    begin  dup 4 pick <  while		( bufend str len direct )
648	    dup d_ino l@ 0<>  if	( bufend str len direct )
649		boot-debug?  if
650		    \ Print the current file name
651		    dup dup d_name swap d_namlen c@ type cr
652		then
653		2dup d_namlen c@ =  if	( bufend str len direct )
654		    dup d_name 2over	( bufend str len direct dname str len )
655		    comp 0= if		( bufend str len direct )
656			\ Found it -- return inode
657			d_ino l@ nip nip nip	( dino )
658			boot-debug?  if  ." Found it" cr  then
659			exit 		( dino )
660		    then
661		then			( bufend str len direct )
662	    then			( bufend str len direct )
663	    dup d_reclen w@ +		( bufend str len nextdirect )
664    repeat
665    2drop 2drop 0
666;
667
668
669: search-directory ( str len -- ino | 0 )
670    0  to  file-offset
671    begin
672	file-offset cur-inode di-size d@ drop <
673    while				( str len )
674	    \ Read a directory block
675	    sb-buf buf-read-file	( str len buf len )
676	    dup 0=  if  ." search-directory: buf-read-file zero len" cr abort  then
677	    dup file-offset +  to  file-offset	( str len buf len )
678
679	    2over 2swap search-dir-block ?dup  if
680		\ Found it
681		nip nip exit
682	    then			( str len )
683    repeat
684    2drop 2drop 0			( 0 )
685;
686
687: read-super ( sector -- )
688   0 " seek" boot-ihandle $call-method -1 =  if
689      ." Seek failed" cr abort
690   then
691   sb-buf sbsize " read" boot-ihandle $call-method
692   dup sbsize <>  if
693      ." Read of superblock failed" cr
694      ." requested" space sbsize .
695      ." actual" space . cr
696      abort
697   else
698      drop
699   then
700;
701
702: check-supers ( -- found? )
703   \ Superblocks used to be 8KB into the partition, but ffsv2 changed that.
704   \ See comments in src/sys/ufs/ffs/fs.h
705   \ Put a list of offets to check on the stack, ending with -1
706   -1
707   0
708   d# 128 KB
709   d# 64 KB
710   8 KB
711
712   begin  dup -1 <>  while			( -1 .. off )
713	 raid-offset dev_bsize * + read-super	( -1 .. )
714	 sb-buf fs-magic?  if			( -1 .. )
715	    begin  -1 =  until	 \ Clean out extra stuff from stack
716	    true exit
717	 then
718   repeat
719   drop false
720;
721
722: ufs-open ( bootpath len -- )
723   boot-ihandle -1 =  if
724      2dup + 0 swap c!	\ Nul terminate.
725      over cif-open dup 0=  if 	( boot-path len ihandle? )
726	 ." Could not open device" space type cr
727	 abort
728      then 				( boot-path len ihandle )
729      to  boot-ihandle			\ Save ihandle to boot device
730   then
731   2drop
732
733   boot-debug?  if ." Try a RAID superblock read" cr  then
734   \ RAIDFRAME skips 64 sectors.
735   d# 64  to  raid-offset
736   check-supers invert  if
737      boot-debug?  if ." Try a normal superblock read" cr  then
738      0  to  raid-offset
739      check-supers 0=  abort" Invalid superblock magic"
740   then
741   sb-buf fs-bsize l@ dup maxbsize >  if
742      ." Superblock bsize" space . ." too large" cr
743      abort
744   then
745   dup fs-size <  if
746      ." Superblock bsize < size of superblock" cr
747      abort
748   then
749   dup  to  cur-blocksize alloc-mem  to  cur-block    \ Allocate cur-block
750   cur-blocksize alloc-mem  to  indir-block
751   boot-debug?  if  ." ufs-open complete" cr  then
752;
753
754: ufs-close ( -- )
755    boot-ihandle dup -1 <>  if
756	cif-close -1  to  boot-ihandle
757    then
758    cur-block 0<> if
759       cur-block cur-blocksize free-mem
760       indir-block cur-blocksize free-mem
761    then
762;
763
764: boot-path ( -- boot-path )
765    " bootpath" chosen-phandle get-package-property  if
766	." Could not find bootpath in /chosen" cr
767	abort
768    else
769	decode-string 2swap 2drop
770    then
771;
772
773: boot-args ( -- boot-args )
774    " bootargs" chosen-phandle get-package-property  if
775	." Could not find bootargs in /chosen" cr
776	abort
777    else
778	decode-string 2swap 2drop
779    then
780;
781
7822000 buffer: boot-path-str
7832000 buffer: boot-path-tmp
784
785: split-path ( path len -- right len left len )
786\ Split a string at the `/'
787    begin
788	dup -rot				( oldlen right len left )
789	ascii / left-parse-string		( oldlen right len left len )
790	dup 0<>  if  4 roll drop exit  then
791	2drop					( oldlen right len )
792	rot over =				( right len diff )
793    until
794;
795
796: find-file ( load-file len -- )
797    rootino dup sb-buf read-inode	( load-file len pino )
798    -rot				( pino load-file len )
799    \
800    \ For each path component
801    \
802    begin  split-path dup 0<>  while	( pino right len left len )
803	    cur-inode is-dir? not  if  ." Inode not directory" cr abort  then
804	    boot-debug?  if  ." Looking for" space 2dup type space ." in directory..." cr  then
805	    search-directory		( pino right len ino|false )
806	    dup 0=  abort" Bad path" 	( pino right len cino )
807	    sb-buf read-inode			( pino right len )
808	    cur-inode is-symlink?  if		\ Symlink -- follow the damn thing
809		\ Save path in boot-path-tmp
810		boot-path-tmp strmov		( pino new-right len )
811
812		\ Now deal with symlink  XXX drop high word of linklen
813		cur-inode di-size d@ drop	( pino right len linklen.lo )
814		dup sb-buf fs_maxsymlinklen l@	( pino right len linklen linklen maxlinklen )
815		<  if				\ Now join the link to the path
816		    0 cur-inode di-db@ drop	( pino right len linklen linkp )
817		    swap boot-path-str strmov	( pino right len new-linkp linklen )
818		else				\ Read file for symlink -- Ugh
819		    \ Read link into boot-path-str
820		    boot-path-str dup sb-buf fs-bsize l@
821		    0 block-map			( pino right len linklen boot-path-str bsize blockno.lo blockno.hi )
822		    strategy drop swap		( pino right len boot-path-str linklen )
823		then 				( pino right len linkp linklen )
824		\ Concatenate the two paths
825		strcat				( pino new-right newlen )
826		swap dup c@ ascii / =  if	\ go to root inode?
827		    rot drop rootino -rot	( rino len right )
828		then
829		rot dup sb-buf read-inode	( len right pino )
830		-rot swap			( pino right len )
831	    then				( pino right len )
832    repeat
833    2drop drop
834;
835
836: .read-file-msg ( addr xxx siz -- addr xxx siz )
837    boot-debug? if
838	." Copying " dup . ." bytes to " 3 pick . cr
839    then
840;
841
842: read-file ( addr size -- )
843    noop \ In case we need to debug this
844    \ Read x bytes from a file to buffer
845    begin  dup 0>  while
846	    file-offset cur-inode di-size d@ drop >  if
847		." read-file EOF exceeded" cr abort
848	    then
849	    sb-buf buf-read-file		( addr size buf len )
850
851	    .read-file-msg
852
853	    \ Copy len bytes to addr  XXX min ( len, size ) ?
854	    2over drop 3dup swap move drop	( addr size buf len )
855
856	    dup file-offset +  to  file-offset	( addr size buf len )
857
858	    nip tuck - -rot + swap		( addr' size' )
859    repeat
860    2drop
861;
862
863" load-base " evaluate constant loader-base
864
865: load-file-signon ( load-file len boot-path len -- load-file len boot-path len )
866   ." Loading file" space 2over type cr ." from device" space 2dup type cr
867;
868
869: load-file ( load-file len boot-path len -- load-base )
870   boot-debug?  if  load-file-signon  then
871
872   ufs-open 				( load-file len )
873   find-file				( )
874
875    \
876    \ Now we've found the file we should read it in in one big hunk
877    \
878
879    cur-inode di-size d@  if  ." File len >2GB!" cr abort  then
880\    dup " to file-size " evaluate	( file-len ) \ Wassthis?
881    boot-debug?  if
882	." Loading " dup . ."  bytes of file..." cr
883    then
884    0  to  file-offset
885    -1  to  file-blockno
886    loader-base				( buf-len addr )
887    tuck swap read-file			( addr )
888    ufs-close				( addr )
889;
890
891: do-boot ( bootfile -- )
892   ." NetBSD IEEE 1275 Multi-FS Bootblock" cr
893   ." Version $NetBSD: bootblk.fth,v 1.13 2010/06/24 00:54:12 eeh Exp $" cr
894   boot-path load-file ( -- load-base )
895   dup 0<>  if  " init-program " evaluate  then
896;
897
898
899boot-args ascii V strchr 0<> swap drop  if
900    true  to  boot-debug?
901then
902
903boot-args ascii D strchr 0= swap drop  if
904    " /ofwboot" do-boot
905then  exit
906
907
908