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]
23 \ Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 \ Use is subject to license terms.
27 purpose: HSFS file system support package for NewBoot
28 copyright: Copyright 2009 Sun Microsystems, Inc. All Rights Reserved
30 \ High Sierra, Rock Ridge (CD-ROM) file system reader and boot block
33 " /packages" get-package push-package
36 fs-pkg$ device-name diag-cr?
41 0 instance value dev-ih
42 0 instance value vol-desc
43 0 instance value dir-buf
44 0 instance value sua-buf
45 0 instance value ce-buf
48 \ HSFS volume descriptor routines
51 \ unaligned load of 2-byte item
53 dup c@ swap char+ ( c0 adr+1 )
58 \ unaligned store of 2-byte item
60 swap wbsplit swap 2 pick c! swap char+ c!
63 \ unaligned load of 4-byte item
65 dup xw@ swap wa1+ ( w0 adr+2 )
69 \ unaligned store of 4-byte item
71 swap lwsplit swap 2 pick xw! swap wa1+ xw!
74 d# 2048 constant /sector
75 d# 16 constant vol-desc-sector# ( -- n )
77 : +vd ( index -- adr )
79 ." invalid access of +vd" cr abort
84 : root-dir ( -- n ) d# 156 +vd ;
85 : /block ( -- n ) d# 128 +vd xw@ ;
86 : byte>blkoff ( byte-off -- block-off ) /block mod ;
89 vol-desc /sector vol-desc-sector# /sector * dev-ih read-disk
92 : read-fs-blocks ( adr len fs-blk# -- ) /block * dev-ih read-disk ;
95 \ HSFS directory routines
98 \ Current directory variables.
99 instance variable cdir-blk \ Current directory device block ptr.
100 instance variable cdir-blk0 \ Current directory block0.
101 instance variable cdir-offset \ Current directory logical offset.
102 instance variable cdir-size \ Current directory logical size.
103 instance variable cdir-ptr \ Current directory entry pointer.
104 false instance value cdir-rescan \ Rescan current directory for symlink.
106 \ Access of current directory entry.
107 : +dr ( n -- adr ) cdir-ptr @ + ;
109 : dir-entrylen ( -- n ) d# 0 +dr c@ ;
110 : dir-block0 ( -- n ) d# 2 +dr xl@ ;
111 : dir-filesize ( -- n ) d# 10 +dr xl@ ;
112 : dir-flags ( -- n ) d# 25 +dr c@ ;
113 : dir-filenamelen ( -- n ) d# 32 +dr c@ ;
114 : dir-filename ( -- adr ) d# 33 +dr ;
116 : dir-isdir? ( -- flag ) dir-flags h# 02 and 0<> ;
117 : dir-file$ ( -- adr len ) dir-filename dir-filenamelen ;
118 : dir-sualen ( -- len ) dir-entrylen d# 33 - dir-filenamelen - ;
120 \ ISO name, including dot & dot-dot check
121 : dir-iso$ ( -- adr len )
122 dir-filenamelen 1 = if
123 dir-filename c@ ( name[0] )
125 drop " ." exit ( dot )
128 " .." exit ( dot-dot )
134 false instance value symlink?
137 dir-buf /block cdir-blk @ read-fs-blocks
141 : froot ( -- ) root-dir cdir-ptr ! ;
144 \ SUAs - System Use Area in directory entry (Rock Ridge
145 \ Extensions to High Sierra/ISO 9660 Format).
146 \ Immediately follows directory entry name rounded up to
147 \ a half-word boundary.
149 0 instance value sua-ptr
150 0 instance value sua-len
152 : +suf ( n -- adr ) sua-ptr + ;
153 : suf-sig ( -- adr len ) sua-ptr 2 ;
154 : suf-len ( -- len ) 2 +suf c@ ;
155 : suf-dat ( -- data ) 5 +suf ;
156 : suf-ce-lbn ( -- lbn ) 4 +suf xl@ ;
157 : suf-ce-offset ( -- offset ) d# 12 +suf xl@ ;
158 : suf-ce-len ( -- len ) d# 20 +suf xl@ ;
161 dir-file$ + /w roundup to sua-ptr
162 dir-sualen to sua-len
166 sua-len suf-len - to sua-len
167 suf-len +suf to sua-ptr
170 : end-sua ( -- end? )
174 : suf-nm$ ( -- adr len ) suf-dat suf-len 5 - ;
176 \ Continuation suffix handling. When a 'CE' suffix is seen,
177 \ record the CE parameters (logical block#, offset and length
178 \ of continuation). We process the CE continuation only after
179 \ we've finished processing the current SUA area.
180 instance variable ce-lbn
181 instance variable ce-offset
182 instance variable ce-len
185 suf-ce-offset ce-offset !
189 : suf-ce-process ( -- error? )
193 sua-buf ce-len @ ce-lbn @ read-fs-blocks
196 0 ce-len ! 0 ce-lbn ! 0 ce-offset !
201 /buf-len instance buffer: suf-sl-buf
202 false instance value symlink-need-sep
204 \ Format of Rock Ridge symlinks needs to be munged to unix-style
205 \ name. Format is: <flag><nbytes>file-name<flag><nbytes>filename...
206 \ where \ <flag> is flag byte (0=filename, 2=current dir, 4=parent
207 \ dir, 8=root dir) and <nbytes> is one-byte byte count (zero for
209 : suf-copy-to-symlinkbuf ( name$ -- )
210 false to symlink-need-sep
211 suf-sl-buf -rot bounds do ( dst )
213 ascii / over c! char+
215 true to symlink-need-sep
216 i c@ dup 2 = if ( dst 2 )
218 drop ascii . over c! char+ 2 ( dst' inc )
219 else dup 4 = if ( dst 4 )
221 drop " .." 2 pick swap move ( dst )
223 else dup 8 = if ( dst 8 )
225 drop ascii / over c! char+ 2 ( dst' inc )
226 false to symlink-need-sep
228 ." unknown SL flag: " .x cr abort
231 i char+ dup c@ >r ( dst src+1 R:nbytes )
232 char+ over r@ move ( dst R:nbytes )
233 r@ + ( dst' R:nbytes )
240 \ Saved 'NM' prefix buffer.
241 /buf-len instance buffer: suf-nm-buf
242 0 instance value suf-nm-size
244 \ Return the Rock Ridge file name associated with the current
245 \ dirent ('NM' suffix). Otherwise returns standard iso filename.
246 \ Marks whether returned filename is a symbolic link ('SL' suffix)
247 \ and also processes continuations ('CE' suffix).
248 : rr-file$ ( -- adr len )
252 \ select start of sua, record sua offset
258 suf-nm-buf suf-nm-size ( NM$ )
265 suf-sig ( sig-adr sig-len )
267 suf-nm$ to suf-nm-size ( sig-adr sig-len suf-nm-adr )
268 suf-nm-buf suf-nm-size move
269 then ( sig-adr sig-len )
272 suf-nm$ suf-copy-to-symlinkbuf
276 then ( sig-adr sig-len )
282 \ HSFS high-level routines
285 \ Used for rescanning current directory for symbolic links.
287 \ Initializes current directory settings from current directory
288 \ entry pointer or for rescan. If it's not a rescan, we have
289 \ access to the actual directory entry, so we can check whether
290 \ it's a directory or not here.
291 : init-dent ( -- error? )
294 cdir-blk0 @ cdir-blk !
299 dir-block0 dup cdir-blk ! cdir-blk0 !
300 dir-filesize cdir-size !
306 : get-dent ( -- error? )
308 \ Check for end of directory, return true if we're past the EOF.
309 cdir-offset @ cdir-size @ >= if
313 \ If we're at a block boundary, get the next block. Otherwise
314 \ increment the directory pointer.
315 cdir-offset @ byte>blkoff 0= if
319 dir-entrylen cdir-ptr +!
322 \ If dir-entrylen is not zero, increment the current directory
323 \ file offset. Otherwise, a dir-entrylen of zero indicates
324 \ the end of a dir block, so round up cdir-offset to fetch the
329 cdir-offset @ /block roundup cdir-offset !
335 \ Look through current directory for file name 'file$'.
336 \ Will leave current directory entry (cdir-ptr) pointing
337 \ to matched entry on success.
338 : dirlook ( file$ -- error? )
342 begin get-dent 0= while ( file$ )
343 2dup rr-file$ $= if ( file$ )
344 2drop false exit ( succeeded )
346 repeat 2drop true ( failed )
349 /buf-len instance buffer: symlink-buf
350 : symlink-buf$ ( -- path$ ) symlink-buf cscount ;
352 : follow-symlink ( tail$ -- tail$' )
354 \ copy symlink value (plus null) to buf
355 suf-sl-buf cscount 1+ symlink-buf swap move
358 \ append to current path
360 " /" symlink-buf$ $append ( tail$ )
361 symlink-buf$ $append ( )
363 symlink-buf$ ( path$ )
364 over c@ ascii / = if ( path$ )
365 froot str++ ( path$' )
371 : lookup ( path$ -- error? )
373 froot str++ ( path$' )
376 ascii / left-parse-string ( path$ file$ )
377 dup while ( path$ file$ )
379 2drop true exit ( failed )
382 follow-symlink ( path$' )
384 repeat ( path$ file$ )
385 2drop 2drop false ( succeeded )
390 \ HSFS installation routines
393 \ Allocate memory for necessary data structures. Need to
394 \ read volume desriptor sector in order to get /block value.
395 : initialize ( -- error? )
396 /sector mem-alloc to vol-desc
398 /block mem-alloc to dir-buf
399 /block mem-alloc to sua-buf
400 /block mem-alloc to ce-buf
403 : release-buffers ( -- )
404 ce-buf /block mem-free
405 sua-buf /block mem-free
406 dir-buf /block mem-free
407 vol-desc /sector mem-free
412 \ HSFS file interface
417 constant /file-record
419 d# 10 constant #opens
420 #opens /file-record * constant /file-records
422 /file-records instance buffer: file-records
424 -1 instance value current-fd
426 : fd>record ( fd -- record ) /file-record * file-records + ;
428 : set-fd ( fd -- error? )
429 dup 0 #opens 1 - between 0= if
432 dup fd>record >block0 x@ 0= if
438 : file-offset@ ( -- off )
439 current-fd fd>record >offset x@
442 : file-offset! ( off -- )
443 current-fd fd>record >offset x!
446 : file-size@ ( -- size )
447 current-fd fd>record >filesize x@
450 : file-size! ( size -- )
451 current-fd fd>record >filesize x!
454 : file-block0@ ( -- block0 )
455 current-fd fd>record >block0 x@
458 : file-block0! ( block0 -- )
459 current-fd fd>record >block0 x!
462 : get-slot ( -- fd false | true )
464 i fd>record >block0 x@ 0= if
470 : free-slot ( fd -- )
478 \ initializes the open structure with information from
479 \ the inode (on UFS) or directory entry (from HSFS).
482 dir-block0 file-block0!
483 dir-filesize file-size!
490 my-args dev-open dup 0= if ( 0 )
495 file-records /file-records erase
504 : open-file ( path$ -- fd true | false )
506 2drop false exit ( failed )
507 then -rot ( fd path$ )
510 drop false exit ( failed )
513 dup init-fd true ( fd success )
516 : close-file ( fd -- )
520 : read-file ( adr len fd -- #read )
522 \ Check if fd is valid, if it is set current-fd.
527 \ Adjust len if less than len bytes remain.
528 file-size@ file-offset@ - min ( adr len' )
530 \ Check for invalid length read.
531 dup 0<= if 2drop 0 exit then
533 \ Compute physical device byte offset.
535 file-block0@ /block * file-offset@ + ( len adr len off )
536 dev-ih read-disk ( #read )
537 dup file-offset@ + file-offset!
540 : seek-file ( off fd -- error? )
542 drop false exit ( failed )
545 dup file-size@ > if ( off )
546 drop false exit ( failed )
548 dup file-offset! true ( off succeeded )
551 : size-file ( fd -- size )
559 \ we don't support compression (yet)
560 : cinfo-file ( fd -- bsize fsize comp? )
561 set-fd if 0 0 0 else /block file-size@ 0 then
564 \ read ramdisk fcode at rd-offset
565 : get-rd ( adr len -- )
566 rd-offset dev-ih read-disk
569 \ no additional props needed for hsfs
570 : bootprop ( -- ) false ;
575 type ." Not found" cr
578 type ." Not a directory" cr
592 begin get-dent 0= while
594 ." flags " dir-flags .x
595 ." blk0 " dir-block0 .x
596 ." size " dir-filesize .x