dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / psm / stand / bootblks / ufs / common / ufs.fth
blobe07cf2ba451c365e6bcaccfc54893038475ed611
2 \ CDDL HEADER START
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.
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.
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]
19 \ CDDL HEADER END
22 \ Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23 \ Use is subject to license terms.
27 purpose: UFS file system support package
28 copyright: Copyright 2009 Sun Microsystems, Inc. All Rights Reserved
30 headers
31 " /packages" get-package  push-package
33 new-device
34    fs-pkg$  device-name  diag-cr?
36    \
37    \    UFS low-level block routines
38    \
40    h# 2000  constant  /max-bsize
41    d# 512   constant  /disk-block
43    0 instance value dev-ih
44    0 instance value temp-block
46    : blk>byte ( block# -- byte# )  /disk-block *  ;
48    : read-disk-blocks  ( adr len dev-block# -- )
49       blk>byte dev-ih  read-disk
50    ;
53    \
54    \    UFS superblock routines
55    \
57    d# 512 constant /super-block
58    d#  16 constant super-block#
59    0 instance value super-block
61    : +sb  ( index -- value )  super-block  swap la+ l@  ;
62    : iblkno    ( -- n )  d# 04 +sb  ;
63    : cgoffset  ( -- n )  d# 06 +sb  ;
64    : cgmask    ( -- n )  d# 07 +sb  ;
65    : bsize     ( -- n )  d# 12 +sb  ;
66    : fragshift ( -- n )  d# 24 +sb  ;
67    : fsbtodbc  ( -- n )  d# 25 +sb  ;
68    : inopb     ( -- n )  d# 30 +sb  ;
69    : ipg       ( -- n )  d# 46 +sb  ;
70    : fpg       ( -- n )  d# 47 +sb  ;
72    : /frag  ( -- fragsize )  bsize fragshift rshift ;
74    : get-super-block  ( -- )
75       super-block /super-block super-block#  read-disk-blocks
76    ;
78    : cgstart   ( cg -- block# )
79       dup cgmask invert and  cgoffset *   swap fpg *  +
80    ;
81    : cgimin       ( cg -- block# )  cgstart  iblkno +  ;
82    : blkstofrags  ( #blocks -- #frags )  fragshift lshift  ;
83    : lblkno       ( byte-off -- lblk# )  bsize /  ;
84    : blkoff       ( byte-off -- blk-off )  bsize mod  ;
85    : fsbtodb      ( fs-blk# -- dev-blk# )  fsbtodbc lshift  ;
87    : read-fs-blocks  ( adr len fs-blk# -- )  fsbtodb read-disk-blocks  ;
90    \
91    \    UFS inode routines
92    \
94    h# 80 constant /inode
95    0 instance value inode
96    0 instance value iptr
98    : itoo  ( i# -- offset )  inopb mod  ;
99    : itog  ( i# -- group )  ipg /  ;
100    : itod  ( i# -- block# )
101       dup itog cgimin  swap ipg mod  inopb /  blkstofrags  +
102    ;
104    : +i  ( n -- adr )  iptr +  ;
106    : ftype ( -- n )  0 +i  w@  h# f000 and  ;
107    : dir?      ( -- flag )  ftype h# 4000 =  ;
108    : symlink?  ( -- flag )  ftype h# a000 =  ;
109    : regular?  ( -- flag )  ftype h# 8000 =  ;
111    : file-size  ( -- n )        8 +i x@  ;
112    : direct0    ( -- adr )  d# 40 +i  ;
113    : indirect0  ( -- adr )  d# 88 +i  ;
114    : indirect1  ( -- adr )  d# 92 +i  ;
115    : indirect2  ( -- adr )  d# 96 +i  ;
116    : comp?      ( -- flag ) d# 100 +i l@  4 and  0<> ;
118    0 instance value current-file
119    : iget  ( i# -- )
120       dup temp-block bsize  rot  itod        ( i# adr len blk# )
121       read-fs-blocks
122       dup itoo  /inode *  temp-block +  inode /inode  move
123       inode to iptr
124       to current-file                        (  )
125    ;
127    : l@++  ( ptr -- value )  dup @ l@  /l rot +!  ;
129    d# 12 constant #direct
130    : #blk-addr/blk  bsize /l /  ;
131    : #sgl-addr      #blk-addr/blk  ;
132    : #dbl-addr      #sgl-addr #blk-addr/blk *  ;
133 \  : #tri-addr      #dbl-addr #blk-addr/blk *  ;
135    : >1-idx ( blk# -- idx )  #blk-addr/blk mod  ;
136    : >2-idx ( blk# -- idx )  #sgl-addr /  >1-idx  ;
137 \  : >3-idx ( blk# -- idx )  #dbl-addr /  >1-idx  ;
139    \
140    \ indirect block cache
141    \ we assume reads will mostly be sequential, and only
142    \ cache the current indirect block tree
143    \
144    : get-indir  ( fs-blk# var adr -- adr )
145       -rot  dup >r   @ over  =  if             ( adr fs-blk#  r: var )
146          r> 2drop  exit                        ( adr )
147       then                                     ( adr fs-blk#  r: var )
148       2dup  bsize swap  read-fs-blocks         ( adr fs-blk#  r: var )
149       r> !                                     ( adr )
150    ;
151       
152    0 instance value indir0-adr
153    instance variable cur-indir0
154    : get-indir0  ( fs-blk# -- adr )
155       cur-indir0 indir0-adr  get-indir
156    ;
158    0 instance value indir1-adr
159    instance variable cur-indir1
160    : get-indir1  ( fs-blk# -- adr )
161       cur-indir1 indir1-adr  get-indir
162    ;
164    \
165    \ blkptr and blklim point to an array of blk#s,
166    \ whether in the inode direct block array or in
167    \ an indirect block
168    \
169    instance variable blkptr
170    instance variable blklim
172    : (bmap)  ( lblk# -- )
173       dup  #direct <  if                           ( lblk# )
174          direct0 swap la+  blkptr  !               (  )
175          direct0 #direct la+  blklim  !
176          exit
177       then                                         ( lblk# )
179       #direct -                                    ( lblk#' )
180       dup  #sgl-addr <  if
181          indirect0 l@  get-indir0                  ( lblk# adr )
182          tuck  swap >1-idx la+  blkptr  !          ( adr )
183          #blk-addr/blk la+  blklim  !
184          exit
185       then                                         ( lblk# )
187       #sgl-addr -                                  ( lblk#' )
188       dup  #dbl-addr <  if
189          indirect1 l@  get-indir0                  ( lblk# adr )
190          over >2-idx la+ l@  get-indir1            ( lblk# adr' )
191          tuck  swap >1-idx la+  blkptr  !          ( adr )
192          #blk-addr/blk la+  blklim  !              (  )
193          exit
194       then                                         ( lblk# )
196 \     #dbl-addr -                                  ( lblk#' )
197 \     dup  #tri-addr <  if
198 \        indirect2 l@  get-indir0                  ( lblk# adr )
199 \        over >3-idx la+ l@  get-indir1            ( lblk# adr' )
200 \        over >2-idx la+ l@  get-indir2            ( lblk# adr' )
201 \        tuck  swap >1-idx la+  blkptr  !          ( adr )
202 \        #blk-addr/blk la+  blklim  !              (  )
203 \        exit
204 \     then                                         ( lblk# )
205       ." file too large" cr  drop true             ( failed )
206    ;
208    0 instance value cur-blk
209    : bmap  ( lblk# -- fs-blk# )
210       dup cur-blk <>  blkptr @  blklim @ =  or  if       ( lblk# )
211          dup (bmap)                                      ( lblk# )
212       then                                               ( lblk# )
213       1+ to cur-blk                                      (  )
214       blkptr l@++                                        ( fs-blk# )
215    ;
217    : read-one-block ( adr block# -- )
218       bmap  ?dup  if
219          bsize swap  read-fs-blocks
220       else
221          bsize  erase
222       then
223    ;
225    : read-partial-block ( adr len off block# -- )
226       bmap  ?dup  if
227          fsbtodb  blk>byte +                        ( adr len byte# )
228          dev-ih  read-disk
229       else
230          drop  erase
231       then
232    ;
234    \
235    \    UFS directory routines
236    \
238    instance variable dir-blk
239    instance variable totoff
240    instance variable dirptr
241    0 instance value dir-buf
243    : get-dirblk  ( -- )
244       dir-buf bsize  dir-blk @  bmap    ( adr len fs-blk# )
245       read-fs-blocks                    ( )
246       1 dir-blk +!
247    ;
249    2 constant rootino
251    : +d  ( n -- adr ) dirptr @  +  ;
253    : dir-ino    ( -- adr ) 0 +d  l@  ;
254    : reclen     ( -- adr ) 4 +d  w@  ;
255    : namelen    ( -- adr ) 6 +d  w@  ;
256    : dir-name   ( -- adr ) 8 +d  ;
257    : dir-name$  ( -- file$ ) dir-name namelen  ;
260    \
261    \    UFS high-level routines
262    \
263    \       After this point, the code should be independent of the disk format!
265    0 instance value search-dir
266    : init-dent
267       0 totoff !  0 dir-blk !
268       current-file to search-dir
269    ;
271    : get-dent ( -- end-of-dir? )
272       begin
273          totoff @  file-size >=  if
274             true  exit
275          then
276          totoff @  blkoff  0=  if
277             get-dirblk
278             dir-buf dirptr !
279          else
280             reclen dirptr +!
281          then
282          reclen totoff +!
283          dir-ino  0<>
284       until  false
285    ;
287    : dirlook  ( file$ -- not-found? )
288       init-dent
289       begin  get-dent 0=  while      ( file$ )
290          2dup  dir-name$  $=  if     ( file$ )
291             dir-ino iget             ( file$ )
292             2drop  false exit        ( found )
293          then                        ( file$ )
294       repeat  2drop true             ( not-found )
295    ;
297    h# 200 constant /fpath-buf
298    /fpath-buf instance buffer: fpath-buf
299    : clr-fpath-buf  ( -- )  fpath-buf /fpath-buf  erase  ;
300    : fpath-buf$  ( -- path$ )  fpath-buf cscount  ;
302    : follow-symlink  ( tail$ -- tail$' )
303       clr-fpath-buf                                         ( tail$ )
304       fpath-buf file-size  0 0  read-partial-block          ( tail$ )
305       ?dup  if                                              ( tail$ )
306          " /" fpath-buf$  $append                           ( tail$ )
307          fpath-buf$  $append                                (  )
308       else  drop  then                                      (  )
309       fpath-buf$                                            ( path$ )
310       over c@  ascii /  =  if                               ( path$ )
311          str++  rootino                                     ( path$' i# )
312       else                                                  ( path$ )
313          search-dir                                         ( path$ i# )
314       then                                                  ( path$ i# )
315       iget                                                  ( path$ )
316    ;
318    : lookup  ( path$ -- not-found? )
319       over c@  ascii /  =  if
320          str++  rootino                           ( path$' i# )
321       else
322          current-file                             ( path$ i# )
323       then                                        ( path$ i# )
324       iget                                        ( path$ )
325       begin                                       ( path$ )
326          ascii / left-parse-string                ( path$ file$ )
327       dup  while
328          dir? 0=  if  2drop true  exit  then
329          dirlook  if  2drop true  exit  then      ( path$ )
330          symlink?  if
331             follow-symlink                        ( path$' )
332          then                                     ( path$ )
333       repeat                                      ( path$ file$ )
334       2drop 2drop  false                          ( succeeded )
335    ;
337    : i#>name ( i# -- name$ )
338       init-dent                      ( i# )
339       begin  get-dent 0=  while      ( i# )
340          dup dir-ino  =  if          ( i# )
341             drop dir-name$  exit     ( name$ )
342          then                        ( i# )
343       repeat  drop " ???"            ( name$ )
344    ;
347    \
348    \    UFS installation routines
349    \
351    /max-bsize  4 *
352    /super-block    +
353    /inode          +
354    constant alloc-size
356    \ **** Allocate memory for necessary data structures
357    : allocate-buffers  ( -- )
358       alloc-size mem-alloc  dup 0=  if
359          ." no memory"  abort
360       then                                ( adr )
361       dup to temp-block   /max-bsize   +  ( adr )
362       dup to dir-buf      /max-bsize   +  ( adr )
363       dup to indir0-adr   /max-bsize   +  ( adr )
364       dup to indir1-adr   /max-bsize   +  ( adr )
365       dup to super-block  /super-block +  ( adr )
366           to inode                        (  )
367    ;
369    : release-buffers  ( -- )
370       temp-block  alloc-size  mem-free
371    ;
373    \ UFS file interface
375    struct
376       /x     field >busy
377       /x     field >offset
378       /inode field >inode
379    constant /file-record
381    d# 10                  constant #opens
382    #opens /file-record *  constant /file-records
384    /file-records  instance buffer: file-records
386    -1 instance value current-fd
387    : fd>record  ( fd -- record )  /file-record *  file-records +  ;
390    : file-offset@  ( -- off )
391       current-fd fd>record >offset  x@
392    ;
394    : file-offset!  ( off -- )
395       current-fd fd>record >offset  x!
396    ;
398    : get-slot  ( -- fd false | true )
399       #opens 0  do
400          i fd>record >busy x@  0=  if
401             i false  unloop exit
402          then
403       loop  true
404    ;
406    : free-slot  ( fd -- )
407       0 swap  fd>record >busy  x!
408    ;
410    : init-fd  ( fd -- )
411       fd>record                ( rec )
412       dup  >busy  1 swap  x!
413       dup  >inode  inode swap  /inode  move
414       >offset  0 swap  x!
415    ;
417    : set-fd  ( fd -- error? )
418       dup fd>record  dup >busy x@  0=  if   ( fd rec )
419          2drop true  exit                   ( failed )
420       then
421       >inode to iptr                        ( fd )
422       to current-fd  false                  ( succeeded )
423    ;
426    \ get current lblk# and offset within it
427    : file-blk+off ( -- off block# )
428       file-offset@ dup  blkoff  swap lblkno
429    ;
431    \ advance file io stack by n
432    : fio+  ( # adr len n -- #+n adr+n len-n )
433       dup file-offset@ +  file-offset!
434       dup >r  -  -rot   ( len' # adr  r: n )
435       r@  +  -rot       ( adr' len' #  r: n )
436       r>  +  -rot       ( #' adr' len' )
437    ;
439    : (cwd)  ( i# -- )  tokenizer[ reveal ]tokenizer
440       dup rootino  <>  if
441          \ open parent, find current name
442          " .." lookup  drop
443          i#>name                ( name$ )
444          \ recurse to print path components above
445          current-file (cwd)     ( name$ )
446          \ and print this component
447          type                   (  )
448       else  drop  then          (  )
449       \ slash is both root name and separator
450       ." /"
451    ;
453    external
455    : open ( -- okay? )
456       my-args dev-open  dup 0=  if       ( 0 )
457          exit                            ( failed )
458       then  to dev-ih
460       allocate-buffers
461       get-super-block
462       file-records /file-records  erase
463       true                               ( succeeded )
464    ;
466    : close  ( -- )
467       dev-ih dev-close
468       0 to dev-ih
469       release-buffers
470    ;
472    : open-file  ( path$ -- fd true | false )
473       get-slot  if
474          2drop false  exit         ( failed )
475       then  -rot                   ( fd path$ )
477       lookup  if                   ( fd )
478          drop false  exit          ( failed )
479       then
481       dup init-fd  true            ( fd succeeded )
482    ;
484    : close-file  ( fd -- )
485       free-slot   (  )
486    ;
488    : size-file  ( fd -- size )
489       set-fd  if  0  else  file-size  then
490    ;
492    : seek-file  ( off fd -- off true | false )
493       set-fd  if                ( off )
494          drop false  exit       ( failed )
495       then                      ( off )
497       dup file-size >  if       ( off )
498          drop false  exit       ( failed )
499       then                      ( off )
500       dup  file-offset!  true   ( off succeeded )
501    ;
503    : read-file  ( adr len fd -- #read )
504       set-fd  if                   ( adr len )
505          2drop 0  exit             ( 0 )
506       then                         ( adr len )
508       regular? 0=  if  2drop 0  exit  then
510       \ adjust len if reading past eof
511       dup  file-offset@ +  file-size  >  if
512          dup  file-offset@ +  file-size -  -
513       then
514       dup 0=  if  nip exit  then
516       0 -rot                              ( #read adr len )
518       \ initial partial block
519       file-offset@ blkoff  ?dup  if       ( #read adr len off )
520          bsize swap -  over  min          ( #read adr len len' )
521          3dup nip  file-blk+off           ( #read adr len len' adr len' off lblk# )
522          read-partial-block               ( #read adr len len )
523          fio+                             ( #read' adr' len' )
524       then                                ( #read adr len )
526       dup lblkno  0  ?do                  ( #read adr len )
527          over  file-blk+off nip           ( #read adr len adr lblk# )
528          read-one-block                   ( #read adr len )
529          bsize fio+                       ( #read' adr' len' )
530       loop                                ( #read adr len )
532       \ final partial block
533       dup  if                             ( #read adr len )
534          2dup  file-blk+off               ( #read adr len adr len off lblk# )
535          read-partial-block               ( #read adr len )
536          dup fio+                         ( #read' adr' 0 )
537       then  2drop                         ( #read )
538    ;
540    : cinfo-file  ( fd -- bsize fsize comp? )
541       set-fd  if  0 0 0  else  bsize file-size comp?  then
542    ;
544    \ read ramdisk fcode at rd-offset
545    : get-rd   ( adr len -- )
546       rd-offset dev-ih  read-disk
547    ;
549    \ no additional props needed for ufs
550    : bootprop  ( -- )  false  ;
552    \ debug words
553    headers
555    : chdir  ( dir$ -- )
556       current-file -rot            ( i# dir$ )
557       lookup  if                   ( i# )
558          to current-file           (  )
559          ." no such dir" cr  exit
560       then                         ( i# )
561       dir? 0=  if                  ( i# )
562          to current-file           (  )
563          ." not a dir" cr  exit
564       then  drop                   (  )
565    ;
567    : dir  ( -- )
568       current-file iget
569       init-dent
570       begin  get-dent 0=  while
571          dir-name$ type  cr
572       repeat
573    ;
575    : cwd  ( -- )
576       current-file        ( i# )
577       dup (cwd)  cr       ( i# )
578       iget                (  )
579    ;
581 finish-device
582 pop-package