Author: mcayland Date: Sat Jul 10 15:11:22 2010 New Revision: 816 URL: http://tracker.coreboot.org/trac/openbios/changeset/816
Log: Currently the dir word works by using /packages/misc-files to open a directory in a similar way to a file and then special-casing directory actions. This is wrong in that in order to list the contents of a directory, open-dev must return true for any device which contains a valid filesystem, regardless of whether or not the supplied arguments reference a valid path.
This causes us a problem because in order to implement multiple references in boot-device correctly, we have to fail if we open a specific device with invalid arguments (such as a non-existent file reference). This patch therefore makes the following changes:
1) Create a static method in each of the filesystem packages to implement dir 2) Enhance the partition/disk handlers to record the phandle of any detected filesystem during open 3) Create a new dir method in the partition/disk handlers which invokes the static dir method for the currently detected filesystem
Hence we can now open a raw device/partition and invoke dir on its filesystem without having to open a specific file-reference first. Following shortly is a patch to switch the main dir word over to use this new system.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk
Modified: trunk/openbios-devel/fs/ext2/ext2_fs.c trunk/openbios-devel/fs/grubfs/grubfs_fs.c trunk/openbios-devel/fs/hfs/hfs_fs.c trunk/openbios-devel/fs/hfsplus/hfsp_fs.c trunk/openbios-devel/fs/iso9660/iso9660_fs.c trunk/openbios-devel/packages/disk-label.c trunk/openbios-devel/packages/mac-parts.c trunk/openbios-devel/packages/pc-parts.c trunk/openbios-devel/packages/sun-parts.c
Modified: trunk/openbios-devel/fs/ext2/ext2_fs.c ============================================================================== --- trunk/openbios-devel/fs/ext2/ext2_fs.c Sun Jul 4 15:37:00 2010 (r815) +++ trunk/openbios-devel/fs/ext2/ext2_fs.c Sat Jul 10 15:11:22 2010 (r816) @@ -33,7 +33,7 @@
DECLARE_NODE( ext2, 0, sizeof(ext2_info_t), "+/packages/ext2-files" );
-/* + static const int days_month[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; static const int days_month_leap[12] = @@ -83,28 +83,6 @@ year, month, day, hour, minute, second); }
-static void -dir_fs ( file_desc_t *fd) -{ - ext2_COMMON *common = (ext2_COMMON *)fd; - struct ext2_dir_entry_2 *entry; - struct ext2_inode inode; - - if (common->type != DIR) - return; - - forth_printf("\n"); - while ( (entry = ext2_readdir(common->dir)) ) { - ext2_get_inode(common->dir->volume, entry->inode, &inode); - forth_printf("% 10d ", inode.i_size); - print_date(inode.i_mtime); - if (S_ISDIR(inode.i_mode)) - forth_printf("%s\\n", entry->name); - else - forth_printf("%s\n", entry->name); - } -} -*/
/************************************************************************/ /* Standard package methods */ @@ -233,6 +211,52 @@ PUSH( (ucell)strdup("ext2") ); }
+/* static method, ( pathstr len ihandle -- ) */ +static void +ext2_files_dir( ext2_info_t *dummy ) +{ + ext2_COMMON *common; + ext2_VOLUME *volume; + struct ext2_dir_entry_2 *entry; + struct ext2_inode inode; + int fd; + + ihandle_t ih = POP(); + char *path = pop_fstr_copy(); + + fd = open_ih( ih ); + if ( fd == -1 ) { + free( path ); + return; + } + + volume = ext2_mount(fd); + if (!volume) { + return; + } + + common = (ext2_COMMON*)malloc(sizeof(ext2_COMMON)); + common->dir = ext2_opendir(volume, path); + + forth_printf("\n"); + while ( (entry = ext2_readdir(common->dir)) ) { + ext2_get_inode(common->dir->volume, entry->inode, &inode); + forth_printf("% 10d ", inode.i_size); + print_date(inode.i_mtime); + if (S_ISDIR(inode.i_mode)) + forth_printf("%s\\n", entry->name); + else + forth_printf("%s\n", entry->name); + } + + ext2_closedir( common->dir ); + ext2_umount( volume ); + + close_io( fd ); + + free( common ); + free( path ); +}
/* static method, ( pos.d ih -- flag? ) */ static void @@ -265,6 +289,7 @@ { "read", ext2_files_read }, { "seek", ext2_files_seek }, { "load", ext2_files_load }, + { "dir", ext2_files_dir },
/* special */ { "get-path", ext2_files_get_path },
Modified: trunk/openbios-devel/fs/grubfs/grubfs_fs.c ============================================================================== --- trunk/openbios-devel/fs/grubfs/grubfs_fs.c Sun Jul 4 15:37:00 2010 (r815) +++ trunk/openbios-devel/fs/grubfs/grubfs_fs.c Sat Jul 10 15:11:22 2010 (r816) @@ -356,6 +356,15 @@ RET ( 0 ); }
+/* static method, ( pathstr len ihandle -- ) */ +static void +grubfs_files_dir( grubfs_info_t *mi ) +{ + forth_printf("dir method not implemented for grubfs filesystem\n"); + POP(); + POP(); + POP(); +}
static void grubfs_initializer( grubfs_info_t *dummy ) @@ -370,6 +379,7 @@ { "read", grubfs_files_read }, { "seek", grubfs_files_seek }, { "load", grubfs_files_load }, + { "dir", grubfs_files_dir },
/* special */ { "get-path", grubfs_files_get_path },
Modified: trunk/openbios-devel/fs/hfs/hfs_fs.c ============================================================================== --- trunk/openbios-devel/fs/hfs/hfs_fs.c Sun Jul 4 15:37:00 2010 (r815) +++ trunk/openbios-devel/fs/hfs/hfs_fs.c Sat Jul 10 15:11:22 2010 (r816) @@ -144,7 +144,6 @@ return mi->common->file; }
-/*
static const int days_month[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; @@ -195,6 +194,7 @@ year, month, day, hour, minute, second); }
+/* static void dir_fs( file_desc_t *fd ) { @@ -485,6 +485,83 @@ PUSH ((ucell)volname); }
+/* static method, ( pathstr len ihandle -- ) */ +static void +hfs_files_dir( hfs_info_t *dummy ) +{ + hfsvol *volume; + hfscommon *common; + hfsdirent ent; + const char *s; + char buf[256], *tmppath; + int fd; + + ihandle_t ih = POP(); + char *path = pop_fstr_copy(); + + fd = open_ih( ih ); + if ( fd == -1 ) { + free( path ); + return; + } + + volume = hfs_mount(fd, 0); + if (!volume) { + return; + } + + common = malloc(sizeof(hfscommon)); + + if (strcmp(path, "\") == 0) { + common->dir = hfs_opendir(volume, ":"); + } else { + if (path[strlen(path) - 1] == '\') { + path[strlen(path) - 1] = 0; + } + + tmppath = path; + for( tmppath-- ;; ) { + int n; + + s = ++tmppath; + tmppath = strchr(s, '\'); + if( !tmppath || !tmppath[1]) + break; + n = MIN( sizeof(buf)-1, (path-s) ); + if( !n ) + continue; + + strncpy( buf, s, n ); + buf[n] = 0; + if( hfs_chdir(volume, buf) ) { + free(common); + free(path); + return; + } + } + + common->dir = hfs_opendir(volume, s); + } + + forth_printf("\n"); + while( !hfs_readdir(common->dir, &ent) ) { + forth_printf("% 10d ", ent.u.file.dsize); + print_date(ent.mddate); + if( ent.flags & HFS_ISDIR ) + forth_printf("%s\\n", ent.name); + else + forth_printf("%s\n", ent.name); + } + + hfs_closedir( common->dir ); + hfs_umount( volume ); + + close_io( fd ); + + free( common ); + free( path ); +} + /* static method, ( pos.d ih -- flag? ) */ static void hfs_files_probe( hfs_info_t *dummy ) @@ -515,6 +592,7 @@ { "read", hfs_files_read }, { "seek", hfs_files_seek }, { "load", hfs_files_load }, + { "dir", hfs_files_dir },
/* special */ { "open-nwrom", hfs_files_open_nwrom },
Modified: trunk/openbios-devel/fs/hfsplus/hfsp_fs.c ============================================================================== --- trunk/openbios-devel/fs/hfsplus/hfsp_fs.c Sun Jul 4 15:37:00 2010 (r815) +++ trunk/openbios-devel/fs/hfsplus/hfsp_fs.c Sat Jul 10 15:11:22 2010 (r816) @@ -24,6 +24,7 @@ #include "unicode.h" #include "blockiter.h" #include "libc/diskio.h" +#include "libc/vsprintf.h"
#define MAC_OS_ROM_CREATOR 0x63687270 /* 'chrp' */ #define MAC_OS_ROM_TYPE 0x74627869 /* 'tbxi' */ @@ -432,6 +433,16 @@ PUSH ((ucell)volname); }
+/* static method, ( pathstr len ihandle -- ) */ +static void +hfsp_files_dir( hfsp_info_t *dummy ) +{ + forth_printf("dir method not implemented for HFS+ filesystem\n"); + POP(); + POP(); + POP(); +} + /* static method, ( pos.d ih -- flag? ) */ static void hfsp_files_probe( hfsp_info_t *dummy ) @@ -449,7 +460,6 @@ RET (ret); }
- static void hfsp_initializer( hfsp_info_t *dummy ) { @@ -463,6 +473,7 @@ { "read", hfsp_files_read }, { "seek", hfsp_files_seek }, { "load", hfsp_files_load }, + { "dir", hfsp_files_dir },
/* special */ { "open-nwrom", hfsp_files_open_nwrom },
Modified: trunk/openbios-devel/fs/iso9660/iso9660_fs.c ============================================================================== --- trunk/openbios-devel/fs/iso9660/iso9660_fs.c Sun Jul 4 15:37:00 2010 (r815) +++ trunk/openbios-devel/fs/iso9660/iso9660_fs.c Sat Jul 10 15:11:22 2010 (r816) @@ -156,17 +156,37 @@ PUSH( size ); }
+/* static method, ( pathstr len ihandle -- ) */ static void -iso9660_files_dir( iso9660_info_t *mi ) +iso9660_files_dir( iso9660_info_t *dummy ) { + iso9660_VOLUME *volume; + iso9660_COMMON *common; struct iso_directory_record *idr; char name_buf[256]; + int fd;
- if (mi->common->type != DIR) + ihandle_t ih = POP(); + char *path = pop_fstr_copy(); + + fd = open_ih( ih ); + if ( fd == -1 ) { + free( path ); return; + } + + volume = iso9660_mount( fd ); + if ( volume == NULL ) { + free ( path ); + close_io( fd ); + return; + } + + common = malloc(sizeof(iso9660_COMMON)); + common->dir = iso9660_opendir( volume, path );
forth_printf("\n"); - while ( (idr = iso9660_readdir(mi->common->dir)) ) { + while ( (idr = iso9660_readdir(common->dir)) ) {
forth_printf("% 10d ", isonum_733(idr->size)); forth_printf("%d-%02d-%02d %02d:%02d:%02d ", @@ -174,12 +194,20 @@ idr->date[1], /* month */ idr->date[2], /* day */ idr->date[3], idr->date[4], idr->date[5]); - iso9660_name(mi->common->dir->volume, idr, name_buf); + iso9660_name(common->dir->volume, idr, name_buf); if (idr->flags[0] & 2) forth_printf("%s\\n", name_buf); else forth_printf("%s\n", name_buf); } + + iso9660_closedir( common->dir ); + iso9660_umount( volume ); + + close_io( fd ); + + free( common ); + free( path ); }
/* static method, ( pos.d ih -- flag? ) */
Modified: trunk/openbios-devel/packages/disk-label.c ============================================================================== --- trunk/openbios-devel/packages/disk-label.c Sun Jul 4 15:37:00 2010 (r815) +++ trunk/openbios-devel/packages/disk-label.c Sat Jul 10 15:11:22 2010 (r816) @@ -41,6 +41,7 @@ int type; /* partition type or -1 */
ihandle_t part_ih; + phandle_t filesystem_ph; } dlabel_info_t;
DECLARE_NODE( dlabel, 0, sizeof(dlabel_info_t), "/packages/disk-label" ); @@ -72,6 +73,7 @@ di->part_ih = 0;
/* Find parent methods */ + di->filesystem_ph = 0; di->parent_seek_xt = find_parent_method("seek"); di->parent_tell_xt = find_parent_method("tell"); di->parent_read_xt = find_parent_method("read"); @@ -115,6 +117,9 @@ ph = POP_ph(); if( ph ) { /* If we have been asked to open a particular file, interpose the filesystem package with the passed filename as an argument */ + di->filesystem_ph = ph; + + DPRINTF("Located filesystem with ph " FMT_ucellx "\n", ph); DPRINTF("path: %s length: %d\n", path, strlen(path));
if (strlen(path)) { @@ -205,6 +210,24 @@ } }
+/* ( pathstr len -- ) */ +static void +dlabel_dir( dlabel_info_t *di ) +{ + if ( di->filesystem_ph ) { + PUSH( my_self() ); + push_str("dir"); + PUSH( di->filesystem_ph ); + fword("find-method"); + POP(); + fword("execute"); + } else { + forth_printf("disk-label: Unable to determine filesystem\n"); + POP(); + POP(); + } +} + NODE_METHODS( dlabel ) = { { "open", dlabel_open }, { "close", dlabel_close }, @@ -213,6 +236,7 @@ { "write", dlabel_write }, { "seek", dlabel_seek }, { "tell", dlabel_tell }, + { "dir", dlabel_dir }, };
void
Modified: trunk/openbios-devel/packages/mac-parts.c ============================================================================== --- trunk/openbios-devel/packages/mac-parts.c Sun Jul 4 15:37:00 2010 (r815) +++ trunk/openbios-devel/packages/mac-parts.c Sat Jul 10 15:11:22 2010 (r816) @@ -181,7 +181,6 @@ ret = -1; goto out; } - } /* not found */ if (firstHFS != -1) { @@ -341,12 +340,34 @@ load(my_self()); }
+/* ( pathstr len -- ) */ +static void +macparts_dir( macparts_info_t *di ) +{ + /* On PPC Mac, the first partition chosen according to the CHRP boot + specification (i.e. marked as bootable) may not necessarily contain + a valid FS */ + if ( di->filesystem_ph ) { + PUSH( my_self() ); + push_str("dir"); + PUSH( di->filesystem_ph ); + fword("find-method"); + POP(); + fword("execute"); + } else { + forth_printf("mac-parts: Unable to determine filesystem\n"); + POP(); + POP(); + } +} + NODE_METHODS( macparts ) = { { "probe", macparts_probe }, { "open", macparts_open }, { "seek", macparts_seek }, { "read", macparts_read }, { "load", macparts_load }, + { "dir", macparts_dir }, { "get-info", macparts_get_info }, { "block-size", macparts_block_size }, { NULL, macparts_initialize },
Modified: trunk/openbios-devel/packages/pc-parts.c ============================================================================== --- trunk/openbios-devel/packages/pc-parts.c Sun Jul 4 15:37:00 2010 (r815) +++ trunk/openbios-devel/packages/pc-parts.c Sat Jul 10 15:11:22 2010 (r816) @@ -365,6 +365,23 @@ load(my_self()); }
+/* ( pathstr len -- ) */ +static void +pcparts_dir( pcparts_info_t *di ) +{ + if ( di->filesystem_ph ) { + PUSH( my_self() ); + push_str("dir"); + PUSH( di->filesystem_ph ); + fword("find-method"); + POP(); + fword("execute"); + } else { + forth_printf("pc-parts: Unable to determine filesystem\n"); + POP(); + POP(); + } +}
NODE_METHODS( pcparts ) = { { "probe", pcparts_probe }, @@ -372,6 +389,7 @@ { "seek", pcparts_seek }, { "read", pcparts_read }, { "load", pcparts_load }, + { "dir", pcparts_dir }, { "get-info", pcparts_get_info }, { "block-size", pcparts_block_size }, { NULL, pcparts_initialize },
Modified: trunk/openbios-devel/packages/sun-parts.c ============================================================================== --- trunk/openbios-devel/packages/sun-parts.c Sun Jul 4 15:37:00 2010 (r815) +++ trunk/openbios-devel/packages/sun-parts.c Sat Jul 10 15:11:22 2010 (r816) @@ -297,6 +297,23 @@ load(my_self()); }
+/* ( pathstr len -- ) */ +static void +sunparts_dir( sunparts_info_t *di ) +{ + if ( di->filesystem_ph) { + PUSH( my_self() ); + push_str("dir"); + PUSH( di->filesystem_ph ); + fword("find-method"); + POP(); + fword("execute"); + } else { + forth_printf("sun-parts: Unable to determine filesystem\n"); + POP(); + POP(); + } +}
NODE_METHODS( sunparts ) = { { "probe", sunparts_probe }, @@ -306,6 +323,7 @@ { "seek", sunparts_seek }, { "read", sunparts_read }, { "load", sunparts_load }, + { "dir", sunparts_dir }, { NULL, sunparts_initialize }, };