[openfirmware] [commit] r1880 - ofw/core
repository service
svn at openfirmware.info
Thu Jul 15 20:27:57 CEST 2010
Author: wmb
Date: Thu Jul 15 20:27:57 2010
New Revision: 1880
URL: http://tracker.coreboot.org/trac/openfirmware/changeset/1880
Log:
Added sparse.c and sparseosfile.fth to svn. They are tools that can be loaded as needed to work on large but sparsely-populated disk images without using up huge amounts of disk space on the host.
Added:
ofw/core/sparse.c
ofw/core/sparseosfile.fth
Added: ofw/core/sparse.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ ofw/core/sparse.c Thu Jul 15 20:27:57 2010 (r1880)
@@ -0,0 +1,47 @@
+// Create a sparse disk image file that can be accessed from OFW
+// running under Linux using /sparseosfile, after loading sparseosfile.fth
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define BLKLEN 4096
+char buf[BLKLEN];
+int blen = BLKLEN;
+
+int allzero(char *buf, size_t len)
+{
+ long *p = (long *)buf;
+ len /= sizeof(long);
+ while (len--)
+ if(*p++)
+ return 0;
+ return 1;
+}
+
+int blockmap[10000];
+
+main(int argc, char **argv)
+{
+ int abs_blockno = 0;
+ int rel_blockno = 0;
+ int outfile;
+
+ outfile = creat("outfile", 0666);
+ if (outfile < 0) {
+ perror("sparse");
+ (void)exit(1);
+ }
+
+ while(read(0, buf, BLKLEN) == BLKLEN) {
+ if (!allzero(buf, BLKLEN)) {
+ write(outfile, buf, BLKLEN);
+ blockmap[rel_blockno++] = abs_blockno;
+ }
+ abs_blockno++;
+ }
+ write(outfile, blockmap, rel_blockno*sizeof(int));
+ write(outfile, &rel_blockno, sizeof(int));
+ write(outfile, &abs_blockno, sizeof(int));
+ write(outfile, &blen, sizeof(int));
+ close(outfile);
+}
Added: ofw/core/sparseosfile.fth
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ ofw/core/sparseosfile.fth Thu Jul 15 20:27:57 2010 (r1880)
@@ -0,0 +1,313 @@
+purpose: Device tree node that accesses a host system file
+\ See license at end of file
+
+\ Creates a device node named "/sparsefile", of device-type "block", which
+\ accesses an operating system file named by its first argument. That
+\ file contains a verbatim disk image in the following sparse format:
+\
+\ Images: N block images
+\ Map: N integers indicating the block number of the corresponding block image
+\ N: integer denoting N
+\ Max: integer denoting the maximum block number for the virtual disk
+\ BlockSize: integer denoting the length of each block image
+
+\ Backslash (\) characters in the file name are translated to
+\ the underlying operating system's directory delimiter.
+\ Example: dir /osfile:\dev\rfd0,\boot\test.fth
+\ Example: dir /osfile:\home\wmb\fs.img,\boot\test.fth
+\ As an alternative to supplying the disk image filename in the device
+\ specifier, you can set "osfile$" to return the name. This is
+\ helpful for cases where the image filename would interfere with
+\ the parsing of later parts of the device specifier.
+\ Example:
+\ dev /osfile
+\ : disk-image$ " /tmp/disk.img" ;
+\ ' disk-image$ to osfile$
+\ dend
+\ dir /osfile:\boot\test.fth
+\ When using the "osfile$" method, you can use either backslash (\) or
+\ the system's native delimiter in the disk image filename. When using
+\ the device specifier argument method, you must use backslash, because
+\ forward slash delimits major device tree components in a device specifier.
+
+dev /
+\ : open true ; : close ;
+
+new-device
+" sparsefile" device-name
+also
+defer sparsefile$ ' null$ to sparsefile$
+0 value file#
+
+\ The deblocker converts a block/record-oriented interface to a byte-oriented
+\ interface, using internal buffering. Disk and tape devices are usually
+\ block or record oriented, but the Open Firmware external interface is
+\ byte-oriented, in order to be independent of particular device block sizes.
+
+0 value deblocker
+: init-deblocker ( -- okay? )
+ " " " deblocker" $open-package is deblocker
+ deblocker if
+ true
+ else
+ ." Can't open deblocker package" cr false
+ then
+;
+
+0 instance value label-package
+0 instance value offset-low
+0 instance value offset-high
+
+: init-label-package ( adr len -- okay? )
+ 0 is offset-high 0 is offset-low
+\ iso9660-file-system
+ " disk-label" $open-package is label-package
+ label-package if
+ 0 0 " offset" label-package $call-method is offset-high is offset-low
+ true
+ else
+ ." Can't open disk label package" cr false
+ then
+;
+: convert/ ( filename$ -- )
+ bounds ?do
+ i c@ [char] \ = if [char] / i c! then
+ loop
+;
+: $fopen ( adr len -- fd ) $cstr 2 swap 8 syscall 2drop retval ;
+: do-seek ( offset whence -- error? ) swap file# _lseek nip ;
+: do-write ( adr len -- error? )
+ file# ['] _fwrite catch if 3drop true else drop false then
+;
+: do-read ( adr len -- error? )
+ file# ['] _fread catch if 3drop true else drop false then
+;
+
+0 value #block-map
+0 value block-map
+0 value #blocks
+0 value #active-blocks
+0 value block-size
+d# 12 buffer: params
+: parse-sparse ( -- error? )
+ 3 /n* negate 2 do-seek if true exit then
+ params 3 /n* do-read if true exit then
+ params @ to #active-blocks
+ params na1+ @ to #blocks
+ params 2 na+ @ to block-size
+ #active-blocks d# 1024 + to #block-map
+ #block-map /n* alloc-mem to block-map
+ #active-blocks /n* negate 3 /n* - 2 do-seek if true exit then
+ block-map #active-blocks /n* do-read if true exit then
+ false
+;
+: save-block-map ( -- )
+ #active-blocks block-size * 0 do-seek if exit then ( )
+ block-map #active-blocks /n* do-write if exit then ( )
+ #active-blocks params !
+ #blocks params na1+ !
+ block-size params 2 na+ !
+ params 3 /n* do-write drop
+;
+
+0 value open-count
+: open ( -- flag )
+ my-args ( arg$ )
+ sparsefile$ dup 0= if ( arg$ null$ )
+ 2drop ( arg$ )
+ ascii , left-parse-string ( arg$' img-filename$ )
+ then ( arg$ img-filename$ )
+
+ open-count if ( arg$ img-filename$ )
+ 2drop ( arg$ )
+ else ( arg$ img-filename$ )
+ 2dup convert/ ( arg$ img-filename$ )
+ $fopen to file# ( arg$ )
+ file# 0< if 2drop false exit then ( arg$ )
+
+ parse-sparse if 2drop false exit then ( arg$ )
+
+ init-deblocker 0= if false exit then ( arg$ )
+ then ( arg$ )
+
+ init-label-package dup 0= if ( flag )
+ open-count 0= if ( flag )
+ deblocker close-package ( false )
+ file# d# 16 syscall drop ( false )
+ then ( flag )
+ then ( flag )
+
+ dup if ( flag )
+ open-count 1+ to open-count ( flag )
+ then ( flag )
+;
+[ifndef] lfind
+[ifdef] 386-assembler
+ code lfind ( sought adr len -- false | index true )
+ cx pop ( cx: len )
+ bx pop ( bx: adr )
+ dx pop ( dx: sought )
+ si push
+ bx si mov ( si: adr )
+ 2 # cx shr ( cx: longword count )
+ begin
+ ax lods
+ ax dx cmp = if
+ bx si sub
+ 2 # si shr
+ si dec
+ si 0 [sp] xchg
+
+ ax ax xor
+ ax dec
+ ax push
+ next
+ then
+ loopa
+ si pop \ Restore si
+ ax ax xor
+ ax push
+ c;
+[then]
+[ifndef] lfind
+ : lfind ( sought adr len -- false | index true )
+ over >r ( sought adr len r: adr )
+ over + search if ( loc r: adr )
+ r> - /n / true ( index true )
+ else ( r: adr )
+ r> drop false ( false )
+ then ( false | index true )
+ ;
+[then]
+[then]
+: >block-index ( block# -- )
+ block-map #active-blocks /n* lfind
+;
+: read-stored-block ( adr index -- error? )
+ block-size * 0 do-seek if drop true exit then ( adr )
+ block-size do-read if true exit then ( )
+ false
+;
+
+: read-block ( adr block# -- error? )
+." R " dup .x
+ dup #blocks >= if 2drop true exit then
+
+ >block-index if ( adr index )
+." I " dup . cr
+ read-stored-block ( error? )
+ else ( adr )
+." Z" cr
+ block-size erase ( )
+ false ( error? )
+ then
+;
+
+: read-blocks ( adr block# #blocks -- actual#blocks )
+ -rot 2 pick ( #blocks adr block# )
+ 0 do ( #blocks adr block# )
+ 2dup read-block if ( #blocks adr block# )
+ 3drop i unloop exit ( -- actual#blocks )
+ then ( #blocks adr block# )
+ swap block-size + swap 1+ ( #blocks adr' block#' )
+ loop ( #blocks adr block# )
+ 2drop ( actual#blocks )
+;
+
+: resize-block-map ( -- error? )
+ block-map #block-map d# 1024 + /n* resize if ( buf-adr )
+ drop true exit ( -- error? )
+ then ( buf-adr )
+ to block-map ( )
+ #block-map d# 1024 + to #block-map ( )
+ false ( error? )
+;
+: write-stored-block ( adr index -- error? )
+ block-size * 0 do-seek if drop true exit then ( adr )
+ block-size do-write if true exit then ( )
+ false
+;
+
+: write-new-block ( adr block# -- error? )
+ #active-blocks #block-map >= if ( adr block# )
+ resize-block-map if 2drop true exit then ( adr block# )
+ then ( adr block# )
+ swap #active-blocks write-stored-block if ( block# )
+ drop true exit ( -- error? )
+ then ( block# )
+ block-map #active-blocks na+ ! ( )
+ #active-blocks 1+ to #active-blocks ( )
+ false ( error? )
+;
+
+: write-block ( adr block# -- error? )
+." W " dup .x
+ dup #blocks >= if ( adr block# )
+ 2drop true exit ( -- error? )
+ then ( adr block# )
+
+ dup >block-index if ( adr block# index )
+." I " dup .x cr
+ nip write-stored-block ( error? )
+ else ( adr block# )
+." N" cr
+ write-new-block ( error? )
+ then ( error? )
+;
+
+: write-blocks ( adr block# #blocks -- actual#blocks )
+ -rot 2 pick ( #blocks adr block# )
+ 0 do ( #blocks adr block# )
+ 2dup write-block if ( #blocks adr block# )
+ 3drop i unloop exit ( -- actual#blocks )
+ then ( #blocks adr block# )
+ swap block-size + swap 1+ ( #blocks adr' block#' )
+ loop ( #blocks adr block# )
+ 2drop ( actual#blocks )
+;
+
+: close ( -- )
+ open-count dup 1- 0 max to open-count ( prev-open-count )
+ label-package close-package ( prev-open-count )
+ 1 = if ( )
+ deblocker close-package ( )
+ save-block-map ( )
+ file# d# 16 syscall drop ( )
+ then ( )
+;
+
+: dma-alloc ( size -- adr ) alloc-mem ;
+: dma-free ( adr size -- ) free-mem ;
+: max-transfer ( -- n ) block-size ;
+
+: seek ( offset.low offset.high -- okay? )
+ offset-low offset-high d+ " seek" deblocker $call-method
+;
+: read ( addr len -- actual-len ) " read" deblocker $call-method ;
+: write ( addr len -- actual-len ) " write" deblocker $call-method ;
+finish-device
+device-end
+
+\ LICENSE_BEGIN
+\ Copyright (c) 2007 FirmWorks
+\
+\ Permission is hereby granted, free of charge, to any person obtaining
+\ a copy of this software and associated documentation files (the
+\ "Software"), to deal in the Software without restriction, including
+\ without limitation the rights to use, copy, modify, merge, publish,
+\ distribute, sublicense, and/or sell copies of the Software, and to
+\ permit persons to whom the Software is furnished to do so, subject to
+\ the following conditions:
+\
+\ The above copyright notice and this permission notice shall be
+\ included in all copies or substantial portions of the Software.
+\
+\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+\
+\ LICENSE_END
More information about the openfirmware
mailing list