summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/fs/hfsplus
diff options
context:
space:
mode:
authorYang Zhang <yang.z.zhang@intel.com>2015-08-28 09:58:54 +0800
committerYang Zhang <yang.z.zhang@intel.com>2015-09-01 12:44:00 +0800
commite44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch)
tree66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/openbios/fs/hfsplus
parent9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff)
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5 Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/openbios/fs/hfsplus')
-rw-r--r--qemu/roms/openbios/fs/hfsplus/build.xml11
-rw-r--r--qemu/roms/openbios/fs/hfsplus/hfsp_blockiter.c141
-rw-r--r--qemu/roms/openbios/fs/hfsplus/hfsp_btree.c372
-rw-r--r--qemu/roms/openbios/fs/hfsplus/hfsp_fs.c632
-rw-r--r--qemu/roms/openbios/fs/hfsplus/hfsp_record.c759
-rw-r--r--qemu/roms/openbios/fs/hfsplus/hfsp_unicode.c511
-rw-r--r--qemu/roms/openbios/fs/hfsplus/hfsp_volume.c323
-rw-r--r--qemu/roms/openbios/fs/hfsplus/include/apple.h111
-rw-r--r--qemu/roms/openbios/fs/hfsplus/include/blockiter.h59
-rw-r--r--qemu/roms/openbios/fs/hfsplus/include/btree.h50
-rw-r--r--qemu/roms/openbios/fs/hfsplus/include/hfs.h32
-rw-r--r--qemu/roms/openbios/fs/hfsplus/include/hfsp.h305
-rw-r--r--qemu/roms/openbios/fs/hfsplus/include/hfstime.h34
-rw-r--r--qemu/roms/openbios/fs/hfsplus/include/libhfsp.h201
-rw-r--r--qemu/roms/openbios/fs/hfsplus/include/record.h80
-rw-r--r--qemu/roms/openbios/fs/hfsplus/include/swab.h64
-rw-r--r--qemu/roms/openbios/fs/hfsplus/include/unicode.h28
-rw-r--r--qemu/roms/openbios/fs/hfsplus/include/volume.h87
-rw-r--r--qemu/roms/openbios/fs/hfsplus/libhfsp.c29
19 files changed, 3829 insertions, 0 deletions
diff --git a/qemu/roms/openbios/fs/hfsplus/build.xml b/qemu/roms/openbios/fs/hfsplus/build.xml
new file mode 100644
index 000000000..5f4c28869
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/build.xml
@@ -0,0 +1,11 @@
+<build>
+ <library name="fs" type="static" target="target">
+ <object source="hfsp_blockiter.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
+ <object source="hfsp_btree.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
+ <object source="libhfsp.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
+ <object source="hfsp_record.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
+ <object source="hfsp_unicode.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
+ <object source="hfsp_volume.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
+ <object source="hfsp_fs.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
+ </library>
+</build>
diff --git a/qemu/roms/openbios/fs/hfsplus/hfsp_blockiter.c b/qemu/roms/openbios/fs/hfsplus/hfsp_blockiter.c
new file mode 100644
index 000000000..e91009229
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/hfsp_blockiter.c
@@ -0,0 +1,141 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ *
+ * The iterator shown here iterates over the blocks of a fork.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original work by 1996-1998 Robert Leslie <rob@mars.org>
+ * other work 2000 from Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: blockiter.c,v 1.2 2000/10/17 05:58:46 hasi Exp $
+ */
+
+#include "config.h"
+#include "libhfsp.h"
+#include "blockiter.h"
+#include "volume.h"
+#include "record.h"
+#include "btree.h"
+#include "os.h"
+#include "swab.h"
+#include "hfstime.h"
+
+/* Initialize iterator for a given fork */
+void
+blockiter_init(blockiter* b, volume* vol, hfsp_fork_raw* f,
+ UInt8 forktype, UInt32 fileId)
+{
+ b->vol = vol;
+ b->curr_block = 0;
+ b->block = 0;
+ b->max_block = f->total_blocks;
+ b->fileId = fileId;
+ b->index = 0;
+ b->file = f->extents;
+ b->e = f->extents;
+ b->forktype = forktype;
+ b->in_extent = 0;
+}
+
+/* get next extent record when needed */
+static int
+blockiter_next_extent(blockiter *b)
+{
+ btree* extents_tree = volume_get_extents_tree(b->vol);
+ int err;
+
+ b->index = 0;
+ if (b->in_extent) // already using extents record ?
+ {
+ err = record_next_extent(&b->er);
+ // Hope there is no need to check this ...
+ // if (b->er.key.start_block != b->curr_block)
+ // HFSP_ERROR(ENOENT,
+ // "Extents record inconistent");
+ }
+ else
+ {
+ err = record_init_file(&b->er, extents_tree, b->forktype,
+ b->fileId, b->curr_block);
+ b->in_extent = -1; // true
+ }
+ b->e = b->er.extent;
+ return err;
+}
+
+/* find next block of the fork iterating over */
+int
+blockiter_next(blockiter *b)
+{
+ b->curr_block ++;
+ b->block ++;
+ if (b->curr_block >= b->max_block)
+ return -1; // end of Blocks, but no error
+ // in current part of extent ?
+ if (b->block >= b->e->block_count)
+ {
+ b->index++;
+ b->block = 0; // reset relative position
+ b->e++;
+ if (b -> index >= 8) // need to fetch another extent
+ {
+ if (blockiter_next_extent(b))
+ HFSP_ERROR(ENOENT, "Extends record not found.");
+ }
+ }
+ return 0;
+
+ fail:
+ return -1;
+}
+
+/* skip the indicated number of blocks */
+int
+blockiter_skip(blockiter *b, UInt32 skip)
+{
+ while (skip > 0)
+ {
+ // Skip to skip or end of current extent
+ UInt32 diff = b->e->block_count - b->block;
+ if (skip < diff)
+ {
+ diff = skip;
+ skip = 0;
+ }
+ else
+ skip -= diff;
+ b->curr_block += diff;
+ b->block += diff;
+ if (b->curr_block >= b->max_block)
+ return -1; // end of Blocks, but no error
+ if (b->block >= b->e->block_count)
+ {
+ b->index++;
+ b->block = 0; // reset relative position
+ b->e++;
+ if (b -> index >= 8) // need to fetch another extent
+ {
+ if (blockiter_next_extent(b))
+ HFSP_ERROR(ENOENT, "Extends record not found.");
+ }
+ }
+ } // we are here when skip was null, thats ok
+ return 0;
+ fail:
+ return -1;
+}
diff --git a/qemu/roms/openbios/fs/hfsplus/hfsp_btree.c b/qemu/roms/openbios/fs/hfsplus/hfsp_btree.c
new file mode 100644
index 000000000..24eca924c
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/hfsp_btree.c
@@ -0,0 +1,372 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * The fucntions are used to handle the various forms of btrees
+ * found on HFS+ volumes.
+ *
+ * The fucntions are used to handle the various forms of btrees
+ * found on HFS+ volumes.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original 1996-1998 Robert Leslie <rob@mars.org>
+ * Additional work by Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: btree.c,v 1.14 2000/10/25 05:43:04 hasi Exp $
+ */
+
+#include "config.h"
+#include "libhfsp.h"
+#include "volume.h"
+#include "btree.h"
+#include "record.h"
+#include "swab.h"
+
+/* Read the node from the given buffer and swap the bytes.
+ *
+ * return pointer after reading the structure
+ */
+static void* btree_readnode(btree_node_desc* node, void *p)
+{
+ node->next = bswabU32_inc(p);
+ node->prev = bswabU32_inc(p);
+ node->kind = bswabU8_inc(p);
+ node->height = bswabU8_inc(p);
+ node->num_rec = bswabU16_inc(p);
+ node->reserved = bswabU16_inc(p);
+ return p;
+}
+
+/* read a btree header from the given buffer and swap the bytes.
+ *
+ * return pointer after reading the structure
+ */
+static void* btree_readhead(btree_head* head, void *p)
+{
+ UInt32 *q;
+ head->depth = bswabU16_inc(p);
+ head->root = bswabU32_inc(p);
+ head->leaf_count = bswabU32_inc(p);
+ head->leaf_head = bswabU32_inc(p);
+ head->leaf_tail = bswabU32_inc(p);
+ head->node_size = bswabU16_inc(p);
+ head->max_key_len = bswabU16_inc(p);
+ head->node_count = bswabU32_inc(p);
+ head->free_nodes = bswabU32_inc(p);
+ head->reserved1 = bswabU16_inc(p);
+ head->clump_size = bswabU32_inc(p);
+ head->btree_type = bswabU8_inc(p);
+ head->reserved2 = bswabU8_inc(p);
+ head->attributes = bswabU32_inc(p);
+ // skip reserved bytes
+ q=((UInt32*) p);
+ // ((UInt32*) p) += 16;
+ q+=16;
+ return q;
+}
+
+/* Priority of the depth of the node compared to LRU value.
+ * Should be the average number of keys per node but these vary. */
+#define DEPTH_FACTOR 1000
+
+/* Cache size is height of tree + this value
+ * Really big numbers wont help in case of ls -R
+ */
+#define EXTRA_CACHESIZE 3
+
+/* Not in use by now ... */
+#define CACHE_DIRTY 0x0001
+
+/* Intialize cache with default cache Size,
+ * must call node_cache_close to deallocate memory */
+static int node_cache_init(node_cache* cache, btree* tree, int size)
+{
+ int nodebufsize;
+ char * buf;
+
+ cache->size = size;
+ cache->currindex = 0;
+ nodebufsize = tree->head.node_size + sizeof(node_buf);
+ buf = malloc(size *(sizeof(node_entry) + nodebufsize));
+ if (!buf)
+ return -1;
+ cache -> nodebufsize = nodebufsize;
+ cache -> entries = (node_entry*) buf;
+ cache -> buffers = (char*) &cache->entries[size];
+ bzero(cache->entries, size*sizeof(node_entry));
+ return 0;
+}
+
+/* Like cache->buffers[i], since size of node_buf is variable */
+static inline node_buf* node_buf_get(node_cache* cache, int i)
+{
+ return (node_buf*) (cache->buffers + (i * cache->nodebufsize));
+}
+
+/* flush the node at index */
+static void node_cache_flush_node(node_cache* cache, int index)
+{
+ // NYI
+ cache -> entries[index].index = 0; // invalidate entry
+}
+
+static void node_cache_close(node_cache* cache)
+{
+ if (!cache->entries) // not (fully) intialized ?
+ return;
+ free(cache->entries);
+}
+
+/* Load the cach node indentified by index with
+ * the node identified by node_index */
+
+static node_buf* node_cache_load_buf
+ (btree* bt, node_cache* cache, int index, UInt16 node_index)
+{
+ node_buf *result = node_buf_get(cache ,index);
+ UInt32 blkpernode = bt->blkpernode;
+ UInt32 block = node_index * blkpernode;
+ void* p = volume_readfromfork(bt->vol, result->node, bt->fork,
+ block, blkpernode, HFSP_EXTENT_DATA, bt->cnid);
+ node_entry *e = &cache->entries[index];
+
+ if (!p)
+ return NULL; // evil ...
+
+ result->index = node_index;
+ btree_readnode(&result->desc, p);
+
+ e -> priority = result->desc.height * DEPTH_FACTOR;
+ e -> index = node_index;
+ return result;
+}
+
+/* Read node at given index, using cache.
+ */
+node_buf* btree_node_by_index(btree* bt, UInt16 index)
+{
+ node_cache* cache = &bt->cache;
+ int oldindex, lruindex;
+ int currindex = cache->currindex;
+ UInt32 prio;
+ node_entry *e;
+
+ // Shortcut acces to current node, will not change priorities
+ if (cache->entries[currindex].index == index)
+ return node_buf_get(cache ,currindex);
+ oldindex = currindex;
+ if (currindex == 0)
+ currindex = cache->size;
+ currindex--;
+ lruindex = oldindex; // entry to be flushed when needed
+ prio = 0; // current priority
+ while (currindex != oldindex) // round robin
+ {
+ e = &cache->entries[currindex];
+ if (e->index == index) // got it
+ {
+ if (e->priority != 0) // already top, uuh
+ e->priority--;
+ cache->currindex = currindex;
+ return node_buf_get(cache ,currindex);
+ }
+ else
+ {
+ if (!e->index)
+ {
+ lruindex = currindex;
+ break; // empty entry, load it
+ }
+ if (e->priority != UINT_MAX) // already least, uuh
+ e->priority++;
+ }
+ if (prio < e->priority)
+ {
+ lruindex = currindex;
+ prio = e->priority;
+ }
+ if (currindex == 0)
+ currindex = cache->size;
+ currindex--;
+ }
+ e = &cache->entries[lruindex];
+ cache->currindex = lruindex;
+ if (e->flags & CACHE_DIRTY)
+ node_cache_flush_node( cache, lruindex);
+ return node_cache_load_buf (bt, cache, lruindex, index);
+}
+
+/** intialize the btree with the first entry in the fork */
+static int btree_init(btree* bt, volume* vol, hfsp_fork_raw* fork)
+{
+ void *p;
+ char buf[vol->blksize];
+ UInt16 node_size;
+ btree_node_desc node;
+
+ bt->vol = vol;
+ bt->fork = fork;
+ p = volume_readfromfork(vol, buf, fork, 0, 1,
+ HFSP_EXTENT_DATA, bt->cnid);
+ if (!p)
+ return -1;
+ p = btree_readnode(&node, p);
+ if (node.kind != HFSP_NODE_HEAD)
+ return -1; // should not happen ?
+ btree_readhead(&bt->head, p);
+
+ node_size = bt->head.node_size;
+ bt->blkpernode = node_size / vol->blksize;
+
+ if (bt->blkpernode == 0 || vol->blksize *
+ bt->blkpernode != node_size)
+ return -1; // should never happen ...
+
+ node_cache_init(&bt->cache, bt, bt->head.depth + EXTRA_CACHESIZE);
+
+ // Allocate buffer
+ // bt->buf = malloc(node_size);
+ // if (!bt->buf)
+ // return ENOMEM;
+
+ return 0;
+}
+
+/** Intialize catalog btree, so that btree_close can safely be called. */
+void btree_reset(btree* bt)
+{
+ bt->cache.entries = NULL;
+}
+
+/** Intialize catalog btree */
+int btree_init_cat(btree* bt, volume* vol, hfsp_fork_raw* fork)
+{
+ int result = btree_init(bt,vol,fork); // super (...)
+ bt->cnid = HFSP_CAT_CNID;
+ bt->kcomp = record_key_compare;
+ bt->kread = record_readkey;
+ return result;
+}
+
+/** Intialize catalog btree */
+int btree_init_extent(btree* bt, volume* vol, hfsp_fork_raw* fork)
+{
+ int result = btree_init(bt,vol,fork); // super (...)
+ bt->cnid = HFSP_EXT_CNID;
+ bt->kcomp = record_extent_key_compare;
+ bt->kread = record_extent_readkey;
+ return result;
+}
+
+/** close the btree and free any resources */
+void btree_close(btree* bt)
+{
+ node_cache_close(&bt->cache);
+ // free(bt->buf);
+}
+
+/* returns pointer to key given by index in current node.
+ *
+ * Assumes that current node is not NODE_HEAD ...
+ */
+void* btree_key_by_index(btree* bt, node_buf* buf, UInt16 index)
+{
+ UInt16 node_size = bt->head.node_size;
+ // The offsets are found at the end of the node ...
+ UInt16 off_pos = node_size - (index +1) * sizeof(btree_record_offset);
+ // position of offset at end of node
+ btree_record_offset* offset =
+ (btree_record_offset*) (buf->node + off_pos);
+
+ // now we have the offset and can read the key ...
+#ifdef CONFIG_LITTLE_ENDIAN
+ return buf->node + bswabU16(*offset);
+#else
+ return buf->node + *offset;
+#endif
+}
+
+
+#ifdef DEBUG
+
+/* print btree header node information */
+void btree_printhead(btree_head* head)
+{
+ UInt32 attr;
+ printf(" depth : %#X\n", head->depth);
+ printf(" root : %#lX\n", head->root);
+ printf(" leaf_count : %#lX\n", head->leaf_count);
+ printf(" leaf_head : %#lX\n", head->leaf_head);
+ printf(" leaf_tail : %#lX\n", head->leaf_tail);
+ printf(" node_size : %#X\n", head->node_size);
+ printf(" max_key_len : %#X\n", head->max_key_len);
+ printf(" node_count : %#lX\n", head->node_count);
+ printf(" free_nodes : %#lX\n", head->free_nodes);
+ printf(" reserved1 : %#X\n", head->reserved1);
+ printf(" clump_size : %#lX\n", head->clump_size);
+ printf(" btree_type : %#X\n", head->btree_type);
+ attr = head->attributes;
+ printf(" reserved2 : %#X\n", head->reserved2);
+ if (attr & HFSPLUS_BAD_CLOSE)
+ printf(" HFSPLUS_BAD_CLOSE *** ");
+ else
+ printf(" !HFSPLUS_BAD_CLOSE");
+ if (attr & HFSPLUS_TREE_BIGKEYS)
+ printf(" HFSPLUS_TREE_BIGKEYS ");
+ else
+ printf(" !HFSPLUS_TREE_BIGKEYS");
+ if (attr & HFSPLUS_TREE_VAR_NDXKEY_SIZE)
+ printf(" HFSPLUS_TREE_VAR_NDXKEY_SIZE");
+ else
+ printf(" !HFSPLUS_TREE_VAR_NDXKEY_SIZE");
+ if (attr & HFSPLUS_TREE_UNUSED)
+ printf(" HFSPLUS_TREE_UNUSED ***\n");
+ printf("\n");
+}
+
+/* Dump all the node information to stdout */
+void btree_print(btree* bt)
+{
+ btree_node_desc* node;
+
+ btree_printhead(&bt->head);
+
+ node = &bt->node;
+ printf("next : %#lX\n", node->next);
+ printf("prev : %#lX\n", node->prev);
+ printf("height : %#X\n", node->height);
+ printf("num_rec : %#X\n", node->num_rec);
+ printf("reserved : %#X\n", node->reserved);
+ printf("height : %#X\n", node->height); switch(node->kind)
+ {
+ case HFSP_NODE_NDX :
+ printf("HFSP_NODE_NDX\n");
+ break;
+ case HFSP_NODE_HEAD :
+ printf("HFSP_NODE_HEAD\n");
+ break;
+ case HFSP_NODE_MAP :
+ printf("HFSP_NODE_MAP\n");
+ break;
+ case HFSP_NODE_LEAF :
+ printf("HFSP_NODE_LEAF\n");
+ break;
+ default:
+ printf("*** Unknown Node type ***\n");
+ }
+}
+
+#endif
diff --git a/qemu/roms/openbios/fs/hfsplus/hfsp_fs.c b/qemu/roms/openbios/fs/hfsplus/hfsp_fs.c
new file mode 100644
index 000000000..df234bb04
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/hfsp_fs.c
@@ -0,0 +1,632 @@
+/*
+ * Creation Date: <2001/05/05 23:33:49 samuel>
+ * Time-stamp: <2004/01/12 10:25:39 samuel>
+ *
+ * /package/hfsplus-files
+ *
+ * HFS+ file system interface (and ROM lookup support)
+ *
+ * Copyright (C) 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "fs/fs.h"
+#include "libhfsp.h"
+#include "volume.h"
+#include "record.h"
+#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' */
+#define MAC_OS_ROM_NAME "Mac OS ROM"
+
+#define FINDER_TYPE 0x464E4452 /* 'FNDR' */
+#define FINDER_CREATOR 0x4D414353 /* 'MACS' */
+#define SYSTEM_TYPE 0x7A737973 /* 'zsys' */
+#define SYSTEM_CREATOR 0x4D414353 /* 'MACS' */
+
+#define VOLNAME_SIZE 64
+
+extern void hfsp_init( void );
+
+typedef struct {
+ record rec;
+ char *path;
+ off_t pos;
+} hfsp_file_t;
+
+typedef struct {
+ volume *vol;
+ hfsp_file_t *hfspfile;
+} hfsp_info_t;
+
+DECLARE_NODE( hfsp, 0, sizeof(hfsp_info_t), "+/packages/hfsplus-files" );
+
+
+/************************************************************************/
+/* Search implementation */
+/************************************************************************/
+
+typedef int (*match_proc_t)( record *r, record *parent, const void *match_data, hfsp_file_t *pt );
+
+static int
+search_files( record *par, int recursive, match_proc_t proc, const void *match_data, hfsp_file_t *pt )
+{
+ hfsp_file_t t;
+ record r;
+ int ret = 1;
+
+ t.path = NULL;
+
+ record_init_parent( &r, par );
+ do{
+ if( r.record.type == HFSP_FOLDER || r.record.type == HFSP_FILE )
+ ret = (*proc)( &r, par, match_data, &t );
+
+ if( ret && r.record.type == HFSP_FOLDER && recursive )
+ ret = search_files( &r, 1, proc, match_data, &t );
+
+ } while( ret && !record_next(&r) );
+
+ if( !ret && pt ) {
+ char name[256];
+ const char *s2 = t.path ? t.path : "";
+
+ unicode_uni2asc( name, &r.key.name, sizeof(name));
+
+ pt->rec = t.rec;
+ pt->path = malloc( strlen(name) + strlen(s2) + 2 );
+ strcpy( pt->path, name );
+ if( strlen(s2) ) {
+ strcat( pt->path, "\\" );
+ strcat( pt->path, s2 );
+ }
+ }
+
+ if( t.path )
+ free( t.path );
+
+ return ret;
+}
+
+static int
+root_search_files( volume *vol, int recursive, match_proc_t proc, const void *match_data, hfsp_file_t *pt )
+{
+ record r;
+
+ record_init_root( &r, &vol->catalog );
+ return search_files( &r, recursive, proc, match_data, pt );
+}
+
+static int
+match_file( record *r, record *parent, const void *match_data, hfsp_file_t *pt )
+{
+ const char *p = (const char*)match_data;
+ char name[256];
+ int ret=1;
+
+ if( r->record.type != HFSP_FILE )
+ return 1;
+
+ (void) unicode_uni2asc(name, &r->key.name, sizeof(name));
+ if( !(ret=strcasecmp(p, name)) && pt )
+ pt->rec = *r;
+
+ return ret;
+}
+
+static int
+match_rom( record *r, record *par, const void *match_data, hfsp_file_t *pt )
+{
+ hfsp_cat_file *file = &r->record.u.file;
+ FInfo *fi = &file->user_info;
+ int ret = 1;
+ char buf[256];
+
+ if( r->record.type == HFSP_FILE && fi->fdCreator == MAC_OS_ROM_CREATOR && fi->fdType == MAC_OS_ROM_TYPE ) {
+ ret = search_files( par, 0, match_file, "System", NULL )
+ || search_files( par, 0, match_file, "Finder", NULL );
+
+ (void) unicode_uni2asc(buf, &r->key.name, sizeof(buf));
+ if( !strcasecmp("BootX", buf) )
+ return 1;
+
+ if( !ret && pt )
+ pt->rec = *r;
+ }
+ return ret;
+}
+
+static int
+match_path( record *r, record *par, const void *match_data, hfsp_file_t *pt )
+{
+ char name[256], *s, *next, *org;
+ int ret=1;
+
+ next = org = strdup( (char*)match_data );
+ while( (s=strsep( &next, "\\/" )) && !strlen(s) )
+ ;
+ if( !s ) {
+ free( org );
+ return 1;
+ }
+
+ if( *s == ':' && strlen(s) == 5 ) {
+ if( r->record.type == HFSP_FILE && !next ) {
+ /* match type */
+ hfsp_cat_file *file = &r->record.u.file;
+ FInfo *fi = &file->user_info;
+ int i, type=0;
+ for( i=1; s[i] && i<=4; i++ )
+ type = (type << 8) | s[i];
+ /* printk("fi->fdType: %s / %s\n", s+1, b ); */
+ if( fi->fdType == type ) {
+ if( pt )
+ pt->rec = *r;
+ ret = 0;
+ }
+ }
+ } else {
+ (void) unicode_uni2asc(name, &r->key.name, sizeof(name));
+
+ if( !strcasecmp(s, name) ) {
+ if( r->record.type == HFSP_FILE && !next ) {
+ if( pt )
+ pt->rec = *r;
+ ret = 0;
+ } else /* must be a directory */
+ ret = search_files( r, 0, match_path, next, pt );
+ }
+ }
+ free( org );
+ return ret;
+}
+
+
+/************************************************************************/
+/* Standard package methods */
+/************************************************************************/
+
+/* ( -- success? ) */
+static void
+hfsp_files_open( hfsp_info_t *mi )
+{
+ int fd;
+ char *path = my_args_copy();
+
+ if ( ! path )
+ RET( 0 );
+
+ fd = open_ih( my_parent() );
+ if ( fd == -1 ) {
+ free( path );
+ RET( 0 );
+ }
+
+ mi->vol = malloc( sizeof(volume) );
+ if (volume_open(mi->vol, fd)) {
+ free( path );
+ close_io( fd );
+ RET( 0 );
+ }
+
+ mi->hfspfile = malloc( sizeof(hfsp_file_t) );
+
+ /* Leading \\ means system folder. The finder info block has
+ * the following meaning.
+ *
+ * [0] Prefered boot directory ID
+ * [3] MacOS 9 boot directory ID
+ * [5] MacOS X boot directory ID
+ */
+ if( !strncmp(path, "\\\\", 2) ) {
+ int *p = (int*)&(mi->vol)->vol.finder_info[0];
+ int cnid = p[0];
+ /* printk(" p[0] = %x, p[3] = %x, p[5] = %x\n", p[0], p[3], p[5] ); */
+ if( p[0] == p[5] && p[3] )
+ cnid = p[3];
+ if( record_init_cnid(&(mi->hfspfile->rec), &(mi->vol)->catalog, cnid) )
+ RET ( 0 );
+ path += 2;
+ } else {
+ record_init_root( &(mi->hfspfile->rec), &(mi->vol)->catalog );
+ }
+
+ if( !search_files(&(mi->hfspfile->rec), 0, match_path, path, mi->hfspfile ) )
+ RET ( -1 );
+
+ RET ( -1 );
+}
+
+/* ( -- ) */
+static void
+hfsp_files_close( hfsp_info_t *mi )
+{
+ volume_close(mi->vol);
+
+ if( mi->hfspfile->path )
+ free( mi->hfspfile->path );
+ free( mi->hfspfile );
+}
+
+/* ( buf len -- actlen ) */
+static void
+hfsp_files_read( hfsp_info_t *mi )
+{
+ int count = POP();
+ char *buf = (char *)cell2pointer(POP());
+
+ hfsp_file_t *t = mi->hfspfile;
+ volume *vol = t->rec.tree->vol;
+ UInt32 blksize = vol->blksize;
+ hfsp_cat_file *file = &t->rec.record.u.file;
+ blockiter iter;
+ char buf2[blksize];
+ int act_count, curpos=0;
+
+ blockiter_init( &iter, vol, &file->data_fork, HFSP_EXTENT_DATA, file->id );
+ while( curpos + blksize < t->pos ) {
+ if( blockiter_next( &iter ) ) {
+ RET ( -1 );
+ return;
+ }
+ curpos += blksize;
+ }
+ act_count = 0;
+
+ while( act_count < count ){
+ UInt32 block = blockiter_curr(&iter);
+ int max = blksize, add = 0, size;
+
+ if( volume_readinbuf( vol, buf2, block ) )
+ break;
+
+ if( curpos < t->pos ){
+ add += t->pos - curpos;
+ max -= t->pos - curpos;
+ }
+ size = (count-act_count > max)? max : count-act_count;
+ memcpy( (char *)buf + act_count, &buf2[add], size );
+
+ curpos += blksize;
+ act_count += size;
+
+ if( blockiter_next( &iter ) )
+ break;
+ }
+
+ t->pos += act_count;
+
+ RET ( act_count );
+}
+
+/* ( pos.d -- status ) */
+static void
+hfsp_files_seek( hfsp_info_t *mi )
+{
+ long long pos = DPOP();
+ int offs = (int)pos;
+ int whence = SEEK_SET;
+
+ hfsp_file_t *t = mi->hfspfile;
+ hfsp_cat_file *file = &t->rec.record.u.file;
+ int total = file->data_fork.total_size;
+
+ if( offs == -1 ) {
+ offs = 0;
+ whence = SEEK_END;
+ }
+
+ switch( whence ){
+ case SEEK_END:
+ t->pos = total + offs;
+ break;
+ default:
+ case SEEK_SET:
+ t->pos = offs;
+ break;
+ }
+
+ if( t->pos < 0 )
+ t->pos = 0;
+
+ if( t->pos > total )
+ t->pos = total;
+
+ RET ( 0 );
+}
+
+/* ( addr -- size ) */
+static void
+hfsp_files_load( hfsp_info_t *mi )
+{
+ char *buf = (char *)cell2pointer(POP());
+
+ hfsp_file_t *t = mi->hfspfile;
+ volume *vol = t->rec.tree->vol;
+ UInt32 blksize = vol->blksize;
+ hfsp_cat_file *file = &t->rec.record.u.file;
+ int total = file->data_fork.total_size;
+ blockiter iter;
+ char buf2[blksize];
+ int act_count;
+
+ blockiter_init( &iter, vol, &file->data_fork, HFSP_EXTENT_DATA, file->id );
+
+ act_count = 0;
+
+ while( act_count < total ){
+ UInt32 block = blockiter_curr(&iter);
+ int max = blksize, size;
+
+ if( volume_readinbuf( vol, buf2, block ) )
+ break;
+
+ size = (total-act_count > max)? max : total-act_count;
+ memcpy( (char *)buf + act_count, &buf2, size );
+
+ act_count += size;
+
+ if( blockiter_next( &iter ) )
+ break;
+ }
+
+ RET ( act_count );
+}
+
+/* ( -- cstr ) */
+static void
+hfsp_files_get_fstype( hfsp_info_t *mi )
+{
+ PUSH( pointer2cell(strdup("HFS+")) );
+}
+
+/* ( -- cstr ) */
+static void
+hfsp_files_get_path( hfsp_info_t *mi )
+{
+ char *buf;
+ hfsp_file_t *t = mi->hfspfile;
+
+ if( !t->path )
+ RET ( 0 );
+
+ buf = malloc(strlen(t->path) + 1);
+ strncpy( buf, t->path, strlen(t->path) );
+ buf[strlen(t->path)] = 0;
+
+ PUSH(pointer2cell(buf));
+}
+
+/* ( -- success? ) */
+static void
+hfsp_files_open_nwrom( hfsp_info_t *mi )
+{
+ /* Switch to an existing ROM image file on the fs! */
+ if( !root_search_files(mi->vol, 1, match_rom, NULL, mi->hfspfile) )
+ RET ( -1 );
+
+ RET ( 0 );
+}
+
+/* ( -- cstr|0 ) */
+static void
+hfsp_files_volume_name( hfsp_info_t *mi )
+{
+ int fd;
+ char *volname = malloc(VOLNAME_SIZE);
+
+ fd = open_ih(my_self());
+ if (fd >= 0) {
+ get_hfs_vol_name(fd, volname, VOLNAME_SIZE);
+ close_io(fd);
+ } else {
+ volname[0] = '\0';
+ }
+
+ PUSH(pointer2cell(volname));
+}
+
+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] =
+ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+static inline int is_leap(int year)
+{
+ return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
+}
+
+static void
+print_date(uint32_t sec)
+{
+ unsigned int second, minute, hour, month, day, year;
+ int current;
+ const int *days;
+
+ second = sec % 60;
+ sec /= 60;
+
+ minute = sec % 60;
+ sec /= 60;
+
+ hour = sec % 24;
+ sec /= 24;
+
+ year = sec * 100 / 36525;
+ sec -= year * 36525 / 100;
+ year += 1904;
+
+ days = is_leap(year) ? days_month_leap : days_month;
+
+ current = 0;
+ month = 0;
+ while (month < 12) {
+ if (sec <= current + days[month]) {
+ break;
+ }
+ current += days[month];
+ month++;
+ }
+ month++;
+
+ day = sec - current + 1;
+
+ forth_printf("%d-%02d-%02d %02d:%02d:%02d ",
+ year, month, day, hour, minute, second);
+}
+
+/* static method, ( pathstr len ihandle -- ) */
+static void
+hfsp_files_dir( hfsp_info_t *dummy )
+{
+ ihandle_t ih = POP_ih();
+ char *path = pop_fstr_copy();
+ int fd, found;
+ volume *vol;
+ record rec, r, folrec;
+ char name[256], *curfol, *tmppath;
+
+ fd = open_ih(ih);
+ if ( fd == -1 ) {
+ free( path );
+ RET( 0 );
+ }
+
+ vol = malloc( sizeof(volume) );
+ if (volume_open(vol, fd)) {
+ free( path );
+ close_io( fd );
+ RET( 0 );
+ }
+
+ /* First move to the specified folder */
+ tmppath = strdup(path);
+ record_init_root( &rec, &vol->catalog );
+ record_init_parent( &r, &rec );
+
+ /* Remove initial \ or / */
+ curfol = strsep(&tmppath, "\\//");
+ curfol = strsep(&tmppath, "\\//");
+ forth_printf("\n");
+
+ while (curfol && strlen(curfol)) {
+ found = 0;
+ do {
+ if (r.record.type == HFSP_FOLDER) {
+ unicode_uni2asc(name, &r.key.name, sizeof(name));
+
+ if (!strcmp(name, curfol)) {
+ folrec = r;
+ found = -1;
+ }
+ }
+ } while ( !record_next(&r) );
+
+ if (!found) {
+ forth_printf("Unable to locate path %s on filesystem\n", path);
+ goto done;
+ } else {
+ record_init_parent( &r, &folrec );
+ }
+
+ curfol = strsep(&tmppath, "\\//");
+ }
+
+ /* Output the directory contents */
+ found = 0;
+ do {
+ unicode_uni2asc(name, &r.key.name, sizeof(name));
+
+ if (r.record.type == HFSP_FILE) {
+ /* Grab the file entry */
+ hfsp_cat_file *file = &r.record.u.file;
+ forth_printf("% 10lld ", file->data_fork.total_size);
+ print_date(file->create_date);
+ forth_printf(" %s\n", name);
+ found = -1;
+ }
+
+ if (r.record.type == HFSP_FOLDER) {
+ /* Grab the directory entry */
+ hfsp_cat_folder *folder = &r.record.u.folder;
+ forth_printf(" 0 ");
+ print_date(folder->create_date);
+ forth_printf(" %s\\\n", name);
+ found = -1;
+ }
+
+ } while ( !record_next(&r) );
+
+ if (!found) {
+ forth_printf(" (Empty folder)\n");
+ }
+
+done:
+ volume_close(vol);
+ free(vol);
+ free(path);
+ if (tmppath)
+ free(tmppath);
+}
+
+/* static method, ( pos.d ih -- flag? ) */
+static void
+hfsp_files_probe( hfsp_info_t *dummy )
+{
+ ihandle_t ih = POP_ih();
+ long long offs = DPOP();
+ int fd, ret = 0;
+
+ fd = open_ih(ih);
+ if (fd >= 0) {
+ if (volume_probe(fd, offs)) {
+ ret = -1;
+ }
+ close_io(fd);
+ } else {
+ ret = -1;
+ }
+
+ RET (ret);
+}
+
+static void
+hfsp_initializer( hfsp_info_t *dummy )
+{
+ fword("register-fs-package");
+}
+
+NODE_METHODS( hfsp ) = {
+ { "probe", hfsp_files_probe },
+ { "open", hfsp_files_open },
+ { "close", hfsp_files_close },
+ { "read", hfsp_files_read },
+ { "seek", hfsp_files_seek },
+ { "load", hfsp_files_load },
+ { "dir", hfsp_files_dir },
+
+ /* special */
+ { "open-nwrom", hfsp_files_open_nwrom },
+ { "get-path", hfsp_files_get_path },
+ { "get-fstype", hfsp_files_get_fstype },
+ { "volume-name", hfsp_files_volume_name },
+
+ { NULL, hfsp_initializer },
+};
+
+void
+hfsp_init( void )
+{
+ REGISTER_NODE( hfsp );
+}
diff --git a/qemu/roms/openbios/fs/hfsplus/hfsp_record.c b/qemu/roms/openbios/fs/hfsplus/hfsp_record.c
new file mode 100644
index 000000000..d4e7af1bf
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/hfsp_record.c
@@ -0,0 +1,759 @@
+/*
+ * libhfsp - library for reading and writing Macintosh HFS+ volumes.
+ *
+ * a record contains a key and a folder or file and is part
+ * of a btree.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original 1996-1998 Robert Leslie <rob@mars.org>
+ * Additional work by Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: record.c,v 1.24 2000/10/17 05:58:46 hasi Exp $
+ */
+
+#include "config.h"
+#include "libhfsp.h"
+#include "hfstime.h"
+#include "record.h"
+#include "volume.h"
+#include "btree.h"
+#include "unicode.h"
+#include "swab.h"
+
+/* read a hfsp_cat_key from memory */
+void* record_readkey(void* p, void* buf)
+{
+ hfsp_cat_key* key = (hfsp_cat_key*) buf;
+ const void* check;
+ UInt16 key_length, len,i;
+ UInt16* cp;
+
+ key->key_length = key_length = bswabU16_inc(p);
+ check = p;
+ key->parent_cnid = bswabU32_inc(p);
+ key->name.strlen = len = bswabU16_inc(p);
+ cp = key->name.name;
+ for (i=0; i < len; i++, cp++)
+ *cp = bswabU16_inc(p);
+ /* check if keylenght was correct */
+ if (key_length != ((char*) p) - ((char*) check))
+ HFSP_ERROR(EINVAL, "Invalid key length in record_readkey");
+ return p;
+ fail:
+ return NULL;
+}
+
+/* read a hfsp_extent_key from memory */
+void* record_extent_readkey(void* p, void* buf)
+{
+ hfsp_extent_key* key = (hfsp_extent_key*) buf;
+ UInt16 key_length;
+
+ key->key_length = key_length = bswabU16_inc(p);
+ key->fork_type = bswabU8_inc(p);
+ key->filler = bswabU8_inc(p);
+ if (key_length != 10)
+ HFSP_ERROR(-1, "Invalid key length in record_extent_readkey");
+ key->file_id = bswabU32_inc(p);
+ key->start_block = bswabU32_inc(p);
+ return p;
+ fail:
+ return NULL;
+}
+
+
+/* read posix permission from memory */
+static inline void* record_readperm(void *p, hfsp_perm* perm)
+{
+ perm->owner= bswabU32_inc(p);
+ perm->group= bswabU32_inc(p);
+ perm->mode = bswabU32_inc(p);
+ perm->dev = bswabU32_inc(p);
+ return p;
+}
+
+/* read directory info */
+static inline void* record_readDInfo(void *p, DInfo* info)
+{
+ info->frRect.top = bswabU16_inc(p);
+ info->frRect.left = bswabU16_inc(p);
+ info->frRect.bottom = bswabU16_inc(p);
+ info->frRect.right = bswabU16_inc(p);
+ info->frFlags = bswabU16_inc(p);
+ info->frLocation.v = bswabU16_inc(p);
+ info->frLocation.h = bswabU16_inc(p);
+ info->frView = bswabU16_inc(p);
+ return p;
+}
+
+/* read extra Directory info */
+static inline void* record_readDXInfo(void *p, DXInfo* xinfo)
+{
+ xinfo->frScroll.v = bswabU16_inc(p);
+ xinfo->frScroll.h = bswabU16_inc(p);
+ xinfo->frOpenChain = bswabU32_inc(p);
+ xinfo->frUnused = bswabU16_inc(p);
+ xinfo->frComment = bswabU16_inc(p);
+ xinfo->frPutAway = bswabU32_inc(p);
+ return p;
+}
+
+/* read a hfsp_cat_folder from memory */
+static void* record_readfolder(void *p, hfsp_cat_folder* folder)
+{
+ folder->flags = bswabU16_inc(p);
+ folder->valence = bswabU32_inc(p);
+ folder->id = bswabU32_inc(p);
+ folder->create_date = bswabU32_inc(p);
+ folder->content_mod_date = bswabU32_inc(p);
+ folder->attribute_mod_date = bswabU32_inc(p);
+ folder->access_date = bswabU32_inc(p);
+ folder->backup_date = bswabU32_inc(p);
+ p = record_readperm (p, &folder->permissions);
+ p = record_readDInfo (p, &folder->user_info);
+ p = record_readDXInfo (p, &folder->finder_info);
+ folder->text_encoding = bswabU32_inc(p);
+ folder->reserved = bswabU32_inc(p);
+ return p;
+}
+
+/* read file info */
+static inline void* record_readFInfo(void *p, FInfo* info)
+{
+ info->fdType = bswabU32_inc(p);
+ info->fdCreator = bswabU32_inc(p);
+ info->fdFlags = bswabU16_inc(p);
+ info->fdLocation.v = bswabU16_inc(p);
+ info->fdLocation.h = bswabU16_inc(p);
+ info->fdFldr = bswabU16_inc(p);
+ return p;
+}
+
+/* read extra File info */
+static inline void* record_readFXInfo(void *p, FXInfo* xinfo)
+{
+ SInt16 *q;
+ xinfo->fdIconID = bswabU16_inc(p);
+ q=(SInt16*) p;
+ q+=4; // skip unused
+ p=(void *)q;
+ xinfo->fdComment = bswabU16_inc(p);
+ xinfo->fdPutAway = bswabU32_inc(p);
+ return p;
+}
+
+/* read a hfsp_cat_file from memory */
+static void* record_readfile(void *p, hfsp_cat_file* file)
+{
+ file->flags = bswabU16_inc(p);
+ file->reserved1 = bswabU32_inc(p);
+ file->id = bswabU32_inc(p);
+ file->create_date = bswabU32_inc(p);
+ file->content_mod_date = bswabU32_inc(p);
+ file->attribute_mod_date = bswabU32_inc(p);
+ file->access_date = bswabU32_inc(p);
+ file->backup_date = bswabU32_inc(p);
+ p = record_readperm (p, &file->permissions);
+ p = record_readFInfo (p, &file->user_info);
+ p = record_readFXInfo (p, &file->finder_info);
+ file->text_encoding = bswabU32_inc(p);
+ file->reserved2 = bswabU32_inc(p);
+ p = volume_readfork (p, &file->data_fork);
+ return volume_readfork (p, &file->res_fork);
+}
+
+/* read a hfsp_cat_thread from memory */
+static void* record_readthread(void *p, hfsp_cat_thread* entry)
+{
+ int i;
+ UInt16 len;
+ UInt16* cp;
+
+ entry-> reserved = bswabU16_inc(p);
+ entry-> parentID = bswabU32_inc(p);
+ entry->nodeName.strlen = len= bswabU16_inc(p);
+ cp = entry->nodeName.name;
+ if (len > 255)
+ HFSP_ERROR(-1, "Invalid key length in record thread");
+ for (i=0; i < len; i++, cp++)
+ *cp = bswabU16_inc(p);
+ return p;
+ fail:
+ return NULL;
+}
+
+/* read a hfsp_cat_entry from memory */
+static void* record_readentry(void *p, hfsp_cat_entry* entry)
+{
+ UInt16 type = bswabU16_inc(p);
+ entry->type = type;
+ switch (type)
+ {
+ case HFSP_FOLDER:
+ return record_readfolder(p, &entry->u.folder);
+ case HFSP_FILE:
+ return record_readfile (p, &entry->u.file);
+ case HFSP_FOLDER_THREAD:
+ case HFSP_FILE_THREAD:
+ return record_readthread(p, &entry->u.thread);
+ default:
+ HFSP_ERROR(-1, "Unexpected record type in record_readentry");
+ } ;
+ fail:
+ return NULL;
+}
+
+
+/* Most of the functions here will not change the node in the btree,
+ But this must be changed in the future ... */
+
+
+/* intialize the record with the given index entry in the btree. */
+static int record_init(record* r, btree* bt, node_buf* buf, UInt16 index)
+{
+ void *p;
+ r-> tree = bt;
+ p = btree_key_by_index(bt,buf,index);
+ if (!p)
+ return -1;
+ p = record_readkey (p, &r->key);
+ if (!p)
+ return -1;
+ p = record_readentry(p, &r->record);
+ if (!p)
+ return -1;
+ r->node_index = buf->index;
+ r-> keyind = index;
+
+ return 0;
+}
+
+/* intialize the record with the given index entry in the btree. */
+static int record_init_extent(extent_record* r, btree* bt, node_buf* buf, UInt16 index)
+{
+ void *p;
+ r-> tree = bt;
+ p = btree_key_by_index(bt, buf,index);
+ if (!p)
+ return -1;
+ p = record_extent_readkey(p, &r->key);
+ if (!p)
+ return -1;
+ p = volume_readextent(p, r->extent);
+ if (!p)
+ return -1;
+ r->node_index = buf->index;
+ r-> keyind = index;
+
+ return 0;
+}
+
+/* intialize the record to the first record of the tree
+ * which is (per design) the root node.
+ */
+int record_init_root(record* r, btree* tree)
+{
+ // Position to first leaf node ...
+ UInt32 leaf_head = tree->head.leaf_head;
+ node_buf* buf = btree_node_by_index(tree, leaf_head);
+ if (!buf)
+ return -1;
+ return record_init(r, tree, buf, 0);
+}
+
+/* Compare two cat_keys ... */
+int record_key_compare(void* k1, void* k2)
+{
+ hfsp_cat_key* key1 = (hfsp_cat_key*) k1;
+ hfsp_cat_key* key2 = (hfsp_cat_key*) k2;
+ int diff = key2->parent_cnid - key1->parent_cnid;
+ if (!diff) // same parent
+ diff = fast_unicode_compare(&key1->name, &key2->name);
+ return diff;
+}
+
+/* Compare two extent_keys ... */
+int record_extent_key_compare(void* k1, void* k2)
+{
+ hfsp_extent_key* key1 = (hfsp_extent_key*) k1;
+ hfsp_extent_key* key2 = (hfsp_extent_key*) k2;
+ int diff = key2->fork_type - key1->fork_type;
+ if (!diff) // same type
+ {
+ diff = key2->file_id - key1->file_id;
+ if (!diff) // same file
+ diff = key2->start_block - key1->start_block;
+ }
+ return diff;
+}
+
+/* Position node in btree so that key might be inside */
+static node_buf* record_find_node(btree* tree, void *key)
+{
+ int start, end, mid, comp; // components of a binary search
+ void *p = NULL;
+ char curr_key[tree->head.max_key_len];
+ // The current key under examination
+ hfsp_key_read readkey = tree->kread;
+ hfsp_key_compare key_compare = tree->kcomp;
+ UInt32 index;
+ node_buf* node = btree_node_by_index(tree, tree->head.root);
+ if (!node)
+ HFSP_ERROR(-1, "record_find_node: Cant position to root node");
+ while (node->desc.kind == HFSP_NODE_NDX)
+ {
+ mid = start = 0;
+ end = node->desc.num_rec;
+ comp = -1;
+ while (start < end)
+ {
+ mid = (start + end) >> 1;
+ p = btree_key_by_index(tree, node, mid);
+ if (!p)
+ HFSP_ERROR(-1, "record_find_node: unexpected error");
+ p = readkey (p, curr_key);
+ if (!p)
+ HFSP_ERROR(-1, "record_find_node: unexpected error");
+ comp = key_compare(curr_key, key);
+ if (comp > 0)
+ start = mid + 1;
+ else if (comp < 0)
+ end = mid;
+ else
+ break;
+ }
+ if (!p) // Empty tree, fascinating ...
+ HFSP_ERROR(-1, "record_find_node: unexpected empty node");
+ if (comp < 0) // mmh interesting key is before this key ...
+ {
+ if (mid == 0)
+ return NULL; // nothing before this key ..
+ p = btree_key_by_index(tree, node, mid-1);
+ if (!p)
+ HFSP_ERROR(-1, "record_find_node: unexpected error");
+ p = readkey (p, curr_key);
+ if (!p)
+ HFSP_ERROR(-1, "record_find_node: unexpected error");
+ }
+
+ index = bswabU32_inc(p);
+ node = btree_node_by_index(tree, index);
+ }
+ return node; // go on and use the found node
+ fail:
+ return NULL;
+}
+
+/* search for the given key in the btree.
+ *
+ * returns pointer to memory just after key or NULL
+ * In any case *keyind recives the index where the
+ * key was found (or could be inserted.)
+ */
+static void *
+record_find_key(btree* tree, void* key, int* keyind, UInt16* node_index)
+{
+ node_buf* buf = record_find_node(tree, key);
+ if (buf)
+ {
+ int comp = -1;
+ int start = 0; // components of a binary search
+ int end = buf->desc.num_rec;
+ int mid = -1;
+ void *p = NULL;
+ char curr_key[tree->head.max_key_len];
+ hfsp_key_read readkey = tree->kread;
+ hfsp_key_compare key_compare = tree->kcomp;
+ while (start < end)
+ {
+ mid = (start + end) >> 1;
+ p = btree_key_by_index(tree, buf, mid);
+ if (!p)
+ HFSP_ERROR(-1, "record_init_key: unexpected error");
+ p = readkey (p, curr_key);
+ if (!p)
+ HFSP_ERROR(-1, "record_init_cat_key: unexpected error");
+ comp = key_compare(curr_key, key);
+ if (comp > 0)
+ start = mid + 1;
+ else if (comp < 0)
+ end = mid;
+ else
+ break;
+ }
+ if (!p) // Empty tree, fascinating ...
+ HFSP_ERROR(ENOENT, "record_init_key: unexpected empty node");
+ *keyind = mid;
+ *node_index = buf->index;
+ if (!comp) // found something ...
+ return p;
+ }
+ HFSP_ERROR(ENOENT, NULL);
+ fail:
+ return NULL;
+}
+
+/* intialize the record by searching for the given key in the btree.
+ *
+ * r is umodified on error.
+ */
+static int
+record_init_key(record* r, btree* tree, hfsp_cat_key* key)
+{
+ int keyind;
+ UInt16 node_index;
+ void *p = record_find_key(tree, key, &keyind, &node_index);
+
+ if (p)
+ {
+ r -> tree = tree;
+ r -> node_index= node_index;
+ r -> keyind = keyind;
+ r -> key = *key; // Better use a record_key_copy ...
+ p = record_readentry(p, &r->record);
+ if (!p)
+ HFSP_ERROR(-1, "record_init_key: unexpected error");
+ return 0;
+ }
+ fail:
+ return -1;
+}
+
+/* intialize the extent_record to the extent identified by the
+ * (first) blockindex.
+ *
+ * forktype: either HFSP_EXTEND_DATA or HFSP_EXTEND_RSRC
+ */
+int record_init_file(extent_record* r, btree* tree,
+ UInt8 forktype, UInt32 fileId, UInt32 blockindex)
+{
+ int keyind;
+ UInt16 node_index;
+ hfsp_extent_key key = { 10, forktype, 0, fileId, blockindex };
+ void *p = record_find_key(tree, &key, &keyind, &node_index);
+
+ if (p)
+ {
+ r -> tree = tree;
+ r -> node_index= node_index;
+ r -> keyind = keyind;
+ r -> key = key; // Better use a record_key_copy ...
+ p = volume_readextent(p, r->extent);
+ if (!p)
+ HFSP_ERROR(-1, "record_init_file: unexpected error");
+ return 0;
+ }
+ fail:
+ return -1;
+}
+
+/* intialize the record to the folder identified by cnid
+ */
+int record_init_cnid(record* r, btree* tree, UInt32 cnid)
+{
+ hfsp_cat_key thread_key; // the thread is the first record
+
+ thread_key.key_length = 6; // null name (like '.' in unix )
+ thread_key.parent_cnid = cnid;
+ thread_key.name.strlen = 0;
+
+ return record_init_key(r, tree, &thread_key);
+}
+
+/* intialize the record to the first record of the parent.
+ */
+int record_init_parent(record* r, record* parent)
+{
+ if (parent->record.type == HFSP_FOLDER)
+ return record_init_cnid(r, parent->tree, parent->record.u.folder.id);
+ else if(parent->record.type == HFSP_FOLDER_THREAD)
+ {
+ if (r != parent)
+ *r = *parent; // The folder thread is in fact the first entry, like '.'
+ return 0;
+ }
+ HFSP_ERROR(EINVAL,
+ "record_init_parent: parent is neither folder nor folder thread.");
+
+ fail:
+ return EINVAL;
+}
+
+
+/* find correct node record for given node and *pindex.
+ *
+ * index of record in this (or next) node
+ * */
+static node_buf* prepare_next(btree* tree, UInt16 node_index, UInt16* pindex)
+{
+ node_buf* buf = btree_node_by_index(tree, node_index);
+ btree_node_desc* desc = &buf->desc;
+ UInt32 numrec = desc->num_rec;
+ if (*pindex >= numrec) // move on to next node
+ {
+ UInt16 next = desc->next;
+ *pindex = 0;
+ if (!next /* is there a next node ? */
+ || !( buf = btree_node_by_index(tree, next)))
+ return NULL;
+ }
+ return buf;
+}
+/* move record foreward to next entry.
+ *
+ * In case of an error the value of *r is undefined !
+ */
+int record_next(record* r)
+{
+ btree* tree = r->tree;
+ UInt16 index = r->keyind +1;
+ UInt32 parent;
+ node_buf* buf = prepare_next(tree, r->node_index, &index);
+
+ if (!buf)
+ return ENOENT; // No (more) such file or directory
+
+ parent = r->key.parent_cnid;
+
+ if (record_init(r, tree, buf, index))
+ return -1;
+
+ if (r->key.parent_cnid != parent || // end of current directory
+ index != r->keyind) // internal error ?
+ return ENOENT; // No (more) such file or directory
+
+ return 0;
+}
+
+/* move record foreward to next extent record.
+ *
+ * In case of an error the value of *r is undefined !
+ */
+int record_next_extent(extent_record* r)
+{
+ btree* tree = r->tree;
+ UInt16 index = r->keyind +1;
+ UInt32 file_id;
+ UInt8 fork_type;
+ node_buf* buf = prepare_next(tree, r->node_index, &index);
+
+ if (!buf)
+ return ENOENT; // No (more) such file or directory
+
+ file_id = r->key.file_id;
+ fork_type = r->key.fork_type;
+
+ if (record_init_extent(r, tree, buf, index))
+ return -1;
+
+ if (r->key.file_id != file_id || // end of current file
+ r->key.fork_type != fork_type || // end of current fork
+ index != r->keyind) // internal error ?
+ return ENOENT; // No (more) such file or directory
+
+ return 0;
+}
+
+/* intialize the record by searching for the given string in the given folder.
+ *
+ * parent and r may be the same.
+ */
+int record_init_string_parent(record* r, record* parent, char* name)
+{
+ hfsp_cat_key key;
+
+ if (parent->record.type == HFSP_FOLDER)
+ key.parent_cnid = parent->record.u.folder.id;
+ else if(parent->record.type == HFSP_FOLDER_THREAD)
+ key.parent_cnid = parent->key.parent_cnid;
+ else
+ HFSP_ERROR(-1, "record_init_string_parent: parent is not a folder.");
+
+ key.key_length = 6 + unicode_asc2uni(&key.name,name); // 6 for minumum size
+ return record_init_key(r, parent->tree, &key);
+
+ fail:
+ return -1;
+}
+
+/* move record up in folder hierarchy (if possible) */
+int record_up(record* r)
+{
+ if (r->record.type == HFSP_FOLDER)
+ {
+ // locate folder thread
+ if (record_init_cnid(r, r->tree, r->record.u.folder.id))
+ return -1;
+ }
+ else if(r->record.type == HFSP_FOLDER_THREAD)
+ {
+ // do nothing were are already where we want to be
+ }
+ else
+ HFSP_ERROR(-1, "record_up: record is neither folder nor folder thread.");
+
+ if(r->record.type != HFSP_FOLDER_THREAD)
+ HFSP_ERROR(-1, "record_up: unable to locate parent");
+ return record_init_cnid(r, r->tree, r->record.u.thread.parentID);
+
+ fail:
+ return -1;
+}
+
+#ifdef DEBUG
+
+/* print Quickdraw Point */
+static void record_print_Point(Point* p)
+{
+ printf("[ v=%d, h=%d ]", p->v, p->h);
+}
+
+/* print Quickdraw Rect */
+static void record_print_Rect(Rect* r)
+{
+ printf("[ top=%d, left=%d, bottom=%d, right=%d ]",
+ r->top, r->left, r->bottom, r->right);
+}
+
+/* print the key of a record */
+static void record_print_key(hfsp_cat_key* key)
+{
+ char buf[255]; // mh this _might_ overflow
+ unicode_uni2asc(buf, &key->name, 255);
+ printf("parent cnid : %ld\n", key->parent_cnid);
+ printf("name : %s\n", buf);
+}
+
+/* print permissions */
+static void record_print_perm(hfsp_perm* perm)
+{
+ printf("owner :\t%ld\n", perm->owner);
+ printf("group :\t%ld\n", perm->group);
+ printf("perm :\t0x%lX\n",perm->mode);
+ printf("dev :\t%ld\n", perm->dev);
+}
+
+/* print Directory info */
+static void record_print_DInfo(DInfo* dinfo)
+{
+ printf( "frRect :\t"); record_print_Rect(&dinfo->frRect);
+ printf("\nfrFlags :\t0X%X\n", dinfo->frFlags);
+ printf( "frLocation :\t"); record_print_Point(&dinfo->frLocation);
+ printf("\nfrView :\t0X%X\n", dinfo->frView);
+}
+
+/* print extended Directory info */
+static void record_print_DXInfo(DXInfo* xinfo)
+{
+ printf( "frScroll :\t"); record_print_Point(&xinfo->frScroll);
+ printf("\nfrOpenChain :\t%ld\n", xinfo->frOpenChain);
+ printf( "frUnused :\t%d\n", xinfo->frUnused);
+ printf( "frComment :\t%d\n", xinfo->frComment);
+ printf( "frPutAway :\t%ld\n", xinfo->frPutAway);
+}
+
+static void record_print_folder(hfsp_cat_folder* folder)
+{
+ printf("flags :\t0x%X\n", folder->flags);
+ printf("valence :\t0x%lX\n", folder->valence);
+ printf("id :\t%ld\n", folder->id);
+ record_print_perm (&folder->permissions);
+ record_print_DInfo (&folder->user_info);
+ record_print_DXInfo (&folder->finder_info);
+ printf("text_encoding :\t0x%lX\n", folder->text_encoding);
+ printf("reserved :\t0x%lX\n", folder->reserved);
+}
+
+/* print File info */
+static void record_print_FInfo(FInfo* finfo)
+{
+ printf( "fdType :\t%4.4s\n", (char*) &finfo->fdType);
+ printf( "fdCreator :\t%4.4s\n", (char*) &finfo->fdCreator);
+ printf( "fdFlags :\t0X%X\n", finfo->fdFlags);
+ printf( "fdLocation :\t"); record_print_Point(&finfo->fdLocation);
+ printf("\nfdFldr :\t%d\n", finfo->fdFldr);
+}
+
+/* print extended File info */
+static void record_print_FXInfo(FXInfo* xinfo)
+{
+ printf( "fdIconID :\t%d\n", xinfo->fdIconID);
+ // xinfo -> fdUnused;
+ printf( "fdComment :\t%d\n", xinfo->fdComment);
+ printf( "fdPutAway :\t%ld\n", xinfo->fdPutAway);
+}
+
+/* print folder entry */
+
+/* print file entry */
+static void record_print_file(hfsp_cat_file* file)
+{
+ printf("flags :\t0x%X\n", file->flags);
+ printf("reserved1 :\t0x%lX\n", file->reserved1);
+ printf("id :\t%ld\n", file->id);
+ record_print_perm (&file->permissions);
+ record_print_FInfo (&file->user_info);
+ record_print_FXInfo (&file->finder_info);
+ printf("text_encoding :\t0x%lX\n", file->text_encoding);
+ printf("reserved :\t0x%lX\n", file->reserved2);
+ printf("Datafork:\n");
+ volume_print_fork (&file->data_fork);
+ printf("Rsrcfork:\n");
+ volume_print_fork (&file->res_fork);
+}
+
+/* print info for a file or folder thread */
+static void record_print_thread(hfsp_cat_thread* entry)
+{
+ char buf[255]; // mh this _might_ overflow
+ unicode_uni2asc(buf, &entry->nodeName, 255);
+ printf("parent cnid :\t%ld\n", entry->parentID);
+ printf("name :\t%s\n" , buf);
+}
+
+/* print the information for a record */
+static void record_print_entry(hfsp_cat_entry* entry)
+{
+ switch (entry->type)
+ {
+ case HFSP_FOLDER:
+ printf("=== Folder ===\n");
+ return record_print_folder(&entry->u.folder);
+ case HFSP_FILE:
+ printf("=== File ===\n");
+ return record_print_file (&entry->u.file);
+ case HFSP_FOLDER_THREAD:
+ printf("=== Folder Thread ===\n");
+ return record_print_thread(&entry->u.thread);
+ case HFSP_FILE_THREAD:
+ printf("=== File Thread ==\n");
+ return record_print_thread(&entry->u.thread);
+ default:
+ printf("=== Unknown Record Type ===\n");
+ } ;
+}
+
+ /* Dump all the record information to stdout */
+void record_print(record* r)
+{
+ printf ("keyind : %u\n", r->keyind);
+ record_print_key (&r->key);
+ record_print_entry(&r->record);
+}
+
+#endif
diff --git a/qemu/roms/openbios/fs/hfsplus/hfsp_unicode.c b/qemu/roms/openbios/fs/hfsplus/hfsp_unicode.c
new file mode 100644
index 000000000..7a34affa1
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/hfsp_unicode.c
@@ -0,0 +1,511 @@
+/*
+ * linux/fs/hfsplus/unicode.c
+ *
+ * Copyright (C) 1999-2000 Brad Boyer (flar@pants.nu)
+ * This file may be distributed under the terms of the GNU Public License.
+ *
+ * The routines found here convert hfs-unicode string into ascii Strings
+ * and vice versa. And the correct comparison between Strings.
+ */
+
+
+#include "config.h"
+#include "libhfsp.h"
+#include "unicode.h"
+
+/* ISO-8859-1 -> unicode */
+static int
+asc2uni( unsigned char *ustr, const char *astr, int maxlen )
+{
+ int len;
+
+ if( maxlen <= 0 )
+ return 0;
+
+ for( len=0; *astr && len < maxlen-1 ; astr++, len++ ) {
+ *ustr++ = 0;
+ *ustr++ = *astr;
+ }
+ ustr[0] = ustr[1] = 0;
+ return len;
+}
+
+/* unicode -> ISO-8859-1 */
+static int
+uni2asc( char *astr, const unsigned char *ustr, int ustrlen, int maxlen )
+{
+ int len;
+
+ if( maxlen <= 0 )
+ return 0;
+
+ for( len=0; ustrlen-- > 0 && len < maxlen-1 ; ustr += 2 ) {
+ /* might be unrepresentable (or too complicated for us) */
+ if( ustr[0] || !ustr[1] )
+ continue;
+ if( ustr[1] < 0x20 || ustr[1] >= 0x7f )
+ *astr++ = '?';
+ else
+ *astr++ = ustr[1];
+ len++;
+ }
+ *astr = 0;
+ return len;
+}
+
+int
+unicode_asc2uni( hfsp_unistr255 *ustr, const char* astr )
+{
+ return ustr->strlen = asc2uni( (u8*)ustr->name, astr, 255 );
+}
+
+int
+unicode_uni2asc(char *astr, const hfsp_unistr255 *ustr, int maxlen)
+{
+ return uni2asc( astr, (u8*)ustr->name, ustr->strlen, maxlen );
+}
+
+/* The following code is almost as published by Apple, only
+ small modifications where made to match some linux styles ...
+
+fastUnicodeCompare - Compare two Unicode strings; produce a relative ordering
+*/
+
+static const UInt16 gLowerCaseTable[];
+
+SInt32 fast_unicode_compare ( const hfsp_unistr255 *ustr1,
+ const hfsp_unistr255 *ustr2)
+{
+ register UInt16 c1,c2;
+ register SInt32 diff;
+ register UInt16 temp;
+ register UInt16 length1 = ustr1->strlen;
+ register UInt16 length2 = ustr2->strlen;
+ register const UInt16* lowerCaseTable = gLowerCaseTable;
+ register const UInt16* str1 = ustr1->name;
+ register const UInt16* str2 = ustr2->name;
+
+ while (1) {
+ // Set default values for c1, c2 in case there are no more valid chars
+ c1 = c2 = 0;
+ // Find next non-ignorable char from str1, or zero if no more
+ while (length1 && c1 == 0) {
+ c1 = *(str1++);
+ --length1;
+ if ((temp = lowerCaseTable[c1>>8]) != 0) // is there a subtable
+ // for this upper byte?
+ c1 = lowerCaseTable[temp + (c1 & 0x00FF)]; // yes, so fold the char
+ }
+ // Find next non-ignorable char from str2, or zero if no more
+ while (length2 && c2 == 0) {
+ c2 = *(str2++);
+ --length2;
+ if ((temp = lowerCaseTable[c2>>8]) != 0) // is there a subtable
+ // for this upper byte?
+ c2 = lowerCaseTable[temp + (c2 & 0x00FF)]; // yes, so fold the char
+ }
+ diff = c2-c1;
+ if (diff) // found a difference, so stop looping
+ break;
+ if (c1 == 0) // did we reach the end of both strings at the same time?
+ return 0; // yes, so strings are equal
+ }
+ return diff;
+}
+
+
+/* The lower case table consists of a 256-entry high-byte table followed by
+ some number of 256-entry subtables. The high-byte table contains either an
+ offset to the subtable for characters with that high byte or zero, which
+ means that there are no case mappings or ignored characters in that block.
+ Ignored characters are mapped to zero.
+ */
+
+static const UInt16 gLowerCaseTable[] = {
+
+ // High-byte indices ( == 0 iff no case mapping and no ignorables )
+
+
+ /* 0 */ 0x0100, 0x0200, 0x0000, 0x0300, 0x0400, 0x0500, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 1 */ 0x0600, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 2 */ 0x0700, 0x0800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 3 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 4 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 5 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 6 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 9 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* A */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* B */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* C */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* D */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* E */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* F */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0900, 0x0A00,
+
+ // Table 1 (for high byte 0x00)
+
+ /* 0 */ 0xFFFF, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ /* 1 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ /* 2 */ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ /* 3 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ /* 4 */ 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ /* 5 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ /* 6 */ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ /* 7 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ /* 8 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ /* 9 */ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ /* A */ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ /* B */ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ /* C */ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00E6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ /* D */ 0x00F0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00F8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00FE, 0x00DF,
+ /* E */ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ /* F */ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF,
+
+ // Table 2 (for high byte 0x01)
+
+ /* 0 */ 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107,
+ 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, 0x010F,
+ /* 1 */ 0x0111, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117,
+ 0x0118, 0x0119, 0x011A, 0x011B, 0x011C, 0x011D, 0x011E, 0x011F,
+ /* 2 */ 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0127, 0x0127,
+ 0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F,
+ /* 3 */ 0x0130, 0x0131, 0x0133, 0x0133, 0x0134, 0x0135, 0x0136, 0x0137,
+ 0x0138, 0x0139, 0x013A, 0x013B, 0x013C, 0x013D, 0x013E, 0x0140,
+ /* 4 */ 0x0140, 0x0142, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147,
+ 0x0148, 0x0149, 0x014B, 0x014B, 0x014C, 0x014D, 0x014E, 0x014F,
+ /* 5 */ 0x0150, 0x0151, 0x0153, 0x0153, 0x0154, 0x0155, 0x0156, 0x0157,
+ 0x0158, 0x0159, 0x015A, 0x015B, 0x015C, 0x015D, 0x015E, 0x015F,
+ /* 6 */ 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165, 0x0167, 0x0167,
+ 0x0168, 0x0169, 0x016A, 0x016B, 0x016C, 0x016D, 0x016E, 0x016F,
+ /* 7 */ 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175, 0x0176, 0x0177,
+ 0x0178, 0x0179, 0x017A, 0x017B, 0x017C, 0x017D, 0x017E, 0x017F,
+ /* 8 */ 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,
+ 0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259,
+ /* 9 */ 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,
+ 0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275,
+ /* A */ 0x01A0, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x01A6, 0x01A8,
+ 0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01AF,
+ /* B */ 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292,
+ 0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,
+ /* C */ 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9,
+ 0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC, 0x01CD, 0x01CE, 0x01CF,
+ /* D */ 0x01D0, 0x01D1, 0x01D2, 0x01D3, 0x01D4, 0x01D5, 0x01D6, 0x01D7,
+ 0x01D8, 0x01D9, 0x01DA, 0x01DB, 0x01DC, 0x01DD, 0x01DE, 0x01DF,
+ /* E */ 0x01E0, 0x01E1, 0x01E2, 0x01E3, 0x01E5, 0x01E5, 0x01E6, 0x01E7,
+ 0x01E8, 0x01E9, 0x01EA, 0x01EB, 0x01EC, 0x01ED, 0x01EE, 0x01EF,
+ /* F */ 0x01F0, 0x01F3, 0x01F3, 0x01F3, 0x01F4, 0x01F5, 0x01F6, 0x01F7,
+ 0x01F8, 0x01F9, 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF,
+
+ // Table 3 (for high byte 0x03)
+
+ /* 0 */ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307,
+ 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F,
+ /* 1 */ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317,
+ 0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F,
+ /* 2 */ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327,
+ 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F,
+ /* 3 */ 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337,
+ 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F,
+ /* 4 */ 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347,
+ 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F,
+ /* 5 */ 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357,
+ 0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F,
+ /* 6 */ 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367,
+ 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F,
+ /* 7 */ 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377,
+ 0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x037F,
+ /* 8 */ 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387,
+ 0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F,
+ /* 9 */ 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
+ 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+ /* A */ 0x03C0, 0x03C1, 0x03A2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
+ 0x03C8, 0x03C9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
+ /* B */ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
+ 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+ /* C */ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
+ 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF,
+ /* D */ 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,
+ 0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF,
+ /* E */ 0x03E0, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7,
+ 0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,
+ /* F */ 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7,
+ 0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF,
+
+ // Table 4 (for high byte 0x04)
+
+ /* 0 */ 0x0400, 0x0401, 0x0452, 0x0403, 0x0454, 0x0455, 0x0456, 0x0407,
+ 0x0458, 0x0459, 0x045A, 0x045B, 0x040C, 0x040D, 0x040E, 0x045F,
+ /* 1 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+ 0x0438, 0x0419, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+ /* 2 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+ 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+ /* 3 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+ 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+ /* 4 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+ 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+ /* 5 */ 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
+ 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F,
+ /* 6 */ 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467,
+ 0x0469, 0x0469, 0x046B, 0x046B, 0x046D, 0x046D, 0x046F, 0x046F,
+ /* 7 */ 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0476, 0x0477,
+ 0x0479, 0x0479, 0x047B, 0x047B, 0x047D, 0x047D, 0x047F, 0x047F,
+ /* 8 */ 0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,
+ 0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F,
+ /* 9 */ 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497,
+ 0x0499, 0x0499, 0x049B, 0x049B, 0x049D, 0x049D, 0x049F, 0x049F,
+ /* A */ 0x04A1, 0x04A1, 0x04A3, 0x04A3, 0x04A5, 0x04A5, 0x04A7, 0x04A7,
+ 0x04A9, 0x04A9, 0x04AB, 0x04AB, 0x04AD, 0x04AD, 0x04AF, 0x04AF,
+ /* B */ 0x04B1, 0x04B1, 0x04B3, 0x04B3, 0x04B5, 0x04B5, 0x04B7, 0x04B7,
+ 0x04B9, 0x04B9, 0x04BB, 0x04BB, 0x04BD, 0x04BD, 0x04BF, 0x04BF,
+ /* C */ 0x04C0, 0x04C1, 0x04C2, 0x04C4, 0x04C4, 0x04C5, 0x04C6, 0x04C8,
+ 0x04C8, 0x04C9, 0x04CA, 0x04CC, 0x04CC, 0x04CD, 0x04CE, 0x04CF,
+ /* D */ 0x04D0, 0x04D1, 0x04D2, 0x04D3, 0x04D4, 0x04D5, 0x04D6, 0x04D7,
+ 0x04D8, 0x04D9, 0x04DA, 0x04DB, 0x04DC, 0x04DD, 0x04DE, 0x04DF,
+ /* E */ 0x04E0, 0x04E1, 0x04E2, 0x04E3, 0x04E4, 0x04E5, 0x04E6, 0x04E7,
+ 0x04E8, 0x04E9, 0x04EA, 0x04EB, 0x04EC, 0x04ED, 0x04EE, 0x04EF,
+ /* F */ 0x04F0, 0x04F1, 0x04F2, 0x04F3, 0x04F4, 0x04F5, 0x04F6, 0x04F7,
+ 0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF,
+
+ // Table 5 (for high byte 0x05)
+
+ /* 0 */ 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507,
+ 0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F,
+ /* 1 */ 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517,
+ 0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F,
+ /* 2 */ 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527,
+ 0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F,
+ /* 3 */ 0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
+ 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
+ /* 4 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
+ 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
+ /* 5 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557,
+ 0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F,
+ /* 6 */ 0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
+ 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
+ /* 7 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
+ 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
+ /* 8 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587,
+ 0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F,
+ /* 9 */ 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597,
+ 0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F,
+ /* A */ 0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7,
+ 0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF,
+ /* B */ 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
+ 0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
+ /* C */ 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7,
+ 0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF,
+ /* D */ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
+ 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
+ /* E */ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
+ 0x05E8, 0x05E9, 0x05EA, 0x05EB, 0x05EC, 0x05ED, 0x05EE, 0x05EF,
+ /* F */ 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7,
+ 0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF,
+
+ // Table 6 (for high byte 0x10)
+
+ /* 0 */ 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
+ 0x1008, 0x1009, 0x100A, 0x100B, 0x100C, 0x100D, 0x100E, 0x100F,
+ /* 1 */ 0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017,
+ 0x1018, 0x1019, 0x101A, 0x101B, 0x101C, 0x101D, 0x101E, 0x101F,
+ /* 2 */ 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
+ 0x1028, 0x1029, 0x102A, 0x102B, 0x102C, 0x102D, 0x102E, 0x102F,
+ /* 3 */ 0x1030, 0x1031, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037,
+ 0x1038, 0x1039, 0x103A, 0x103B, 0x103C, 0x103D, 0x103E, 0x103F,
+ /* 4 */ 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047,
+ 0x1048, 0x1049, 0x104A, 0x104B, 0x104C, 0x104D, 0x104E, 0x104F,
+ /* 5 */ 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057,
+ 0x1058, 0x1059, 0x105A, 0x105B, 0x105C, 0x105D, 0x105E, 0x105F,
+ /* 6 */ 0x1060, 0x1061, 0x1062, 0x1063, 0x1064, 0x1065, 0x1066, 0x1067,
+ 0x1068, 0x1069, 0x106A, 0x106B, 0x106C, 0x106D, 0x106E, 0x106F,
+ /* 7 */ 0x1070, 0x1071, 0x1072, 0x1073, 0x1074, 0x1075, 0x1076, 0x1077,
+ 0x1078, 0x1079, 0x107A, 0x107B, 0x107C, 0x107D, 0x107E, 0x107F,
+ /* 8 */ 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087,
+ 0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F,
+ /* 9 */ 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097,
+ 0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x109F,
+ /* A */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7,
+ 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF,
+ /* B */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7,
+ 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF,
+ /* C */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10C6, 0x10C7,
+ 0x10C8, 0x10C9, 0x10CA, 0x10CB, 0x10CC, 0x10CD, 0x10CE, 0x10CF,
+ /* D */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7,
+ 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF,
+ /* E */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7,
+ 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF,
+ /* F */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10F6, 0x10F7,
+ 0x10F8, 0x10F9, 0x10FA, 0x10FB, 0x10FC, 0x10FD, 0x10FE, 0x10FF,
+
+ // Table 7 (for high byte 0x20)
+
+ /* 0 */ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
+ 0x2008, 0x2009, 0x200A, 0x200B, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 1 */ 0x2010, 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017,
+ 0x2018, 0x2019, 0x201A, 0x201B, 0x201C, 0x201D, 0x201E, 0x201F,
+ /* 2 */ 0x2020, 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027,
+ 0x2028, 0x2029, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x202F,
+ /* 3 */ 0x2030, 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037,
+ 0x2038, 0x2039, 0x203A, 0x203B, 0x203C, 0x203D, 0x203E, 0x203F,
+ /* 4 */ 0x2040, 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047,
+ 0x2048, 0x2049, 0x204A, 0x204B, 0x204C, 0x204D, 0x204E, 0x204F,
+ /* 5 */ 0x2050, 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057,
+ 0x2058, 0x2059, 0x205A, 0x205B, 0x205C, 0x205D, 0x205E, 0x205F,
+ /* 6 */ 0x2060, 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067,
+ 0x2068, 0x2069, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 7 */ 0x2070, 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077,
+ 0x2078, 0x2079, 0x207A, 0x207B, 0x207C, 0x207D, 0x207E, 0x207F,
+ /* 8 */ 0x2080, 0x2081, 0x2082, 0x2083, 0x2084, 0x2085, 0x2086, 0x2087,
+ 0x2088, 0x2089, 0x208A, 0x208B, 0x208C, 0x208D, 0x208E, 0x208F,
+ /* 9 */ 0x2090, 0x2091, 0x2092, 0x2093, 0x2094, 0x2095, 0x2096, 0x2097,
+ 0x2098, 0x2099, 0x209A, 0x209B, 0x209C, 0x209D, 0x209E, 0x209F,
+ /* A */ 0x20A0, 0x20A1, 0x20A2, 0x20A3, 0x20A4, 0x20A5, 0x20A6, 0x20A7,
+ 0x20A8, 0x20A9, 0x20AA, 0x20AB, 0x20AC, 0x20AD, 0x20AE, 0x20AF,
+ /* B */ 0x20B0, 0x20B1, 0x20B2, 0x20B3, 0x20B4, 0x20B5, 0x20B6, 0x20B7,
+ 0x20B8, 0x20B9, 0x20BA, 0x20BB, 0x20BC, 0x20BD, 0x20BE, 0x20BF,
+ /* C */ 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7,
+ 0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x20CF,
+ /* D */ 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7,
+ 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x20DF,
+ /* E */ 0x20E0, 0x20E1, 0x20E2, 0x20E3, 0x20E4, 0x20E5, 0x20E6, 0x20E7,
+ 0x20E8, 0x20E9, 0x20EA, 0x20EB, 0x20EC, 0x20ED, 0x20EE, 0x20EF,
+ /* F */ 0x20F0, 0x20F1, 0x20F2, 0x20F3, 0x20F4, 0x20F5, 0x20F6, 0x20F7,
+ 0x20F8, 0x20F9, 0x20FA, 0x20FB, 0x20FC, 0x20FD, 0x20FE, 0x20FF,
+
+ // Table 8 (for high byte 0x21)
+
+ /* 0 */ 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107,
+ 0x2108, 0x2109, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F,
+ /* 1 */ 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117,
+ 0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F,
+ /* 2 */ 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x2126, 0x2127,
+ 0x2128, 0x2129, 0x212A, 0x212B, 0x212C, 0x212D, 0x212E, 0x212F,
+ /* 3 */ 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137,
+ 0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, 0x213F,
+ /* 4 */ 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147,
+ 0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F,
+ /* 5 */ 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157,
+ 0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F,
+ /* 6 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
+ 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
+ /* 7 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
+ 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
+ /* 8 */ 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187,
+ 0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, 0x218F,
+ /* 9 */ 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197,
+ 0x2198, 0x2199, 0x219A, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F,
+ /* A */ 0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7,
+ 0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF,
+ /* B */ 0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7,
+ 0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF,
+ /* C */ 0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7,
+ 0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF,
+ /* D */ 0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7,
+ 0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF,
+ /* E */ 0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7,
+ 0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF,
+ /* F */ 0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7,
+ 0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF,
+
+ // Table 9 (for high byte 0xFE)
+
+ /* 0 */ 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07,
+ 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F,
+ /* 1 */ 0xFE10, 0xFE11, 0xFE12, 0xFE13, 0xFE14, 0xFE15, 0xFE16, 0xFE17,
+ 0xFE18, 0xFE19, 0xFE1A, 0xFE1B, 0xFE1C, 0xFE1D, 0xFE1E, 0xFE1F,
+ /* 2 */ 0xFE20, 0xFE21, 0xFE22, 0xFE23, 0xFE24, 0xFE25, 0xFE26, 0xFE27,
+ 0xFE28, 0xFE29, 0xFE2A, 0xFE2B, 0xFE2C, 0xFE2D, 0xFE2E, 0xFE2F,
+ /* 3 */ 0xFE30, 0xFE31, 0xFE32, 0xFE33, 0xFE34, 0xFE35, 0xFE36, 0xFE37,
+ 0xFE38, 0xFE39, 0xFE3A, 0xFE3B, 0xFE3C, 0xFE3D, 0xFE3E, 0xFE3F,
+ /* 4 */ 0xFE40, 0xFE41, 0xFE42, 0xFE43, 0xFE44, 0xFE45, 0xFE46, 0xFE47,
+ 0xFE48, 0xFE49, 0xFE4A, 0xFE4B, 0xFE4C, 0xFE4D, 0xFE4E, 0xFE4F,
+ /* 5 */ 0xFE50, 0xFE51, 0xFE52, 0xFE53, 0xFE54, 0xFE55, 0xFE56, 0xFE57,
+ 0xFE58, 0xFE59, 0xFE5A, 0xFE5B, 0xFE5C, 0xFE5D, 0xFE5E, 0xFE5F,
+ /* 6 */ 0xFE60, 0xFE61, 0xFE62, 0xFE63, 0xFE64, 0xFE65, 0xFE66, 0xFE67,
+ 0xFE68, 0xFE69, 0xFE6A, 0xFE6B, 0xFE6C, 0xFE6D, 0xFE6E, 0xFE6F,
+ /* 7 */ 0xFE70, 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE75, 0xFE76, 0xFE77,
+ 0xFE78, 0xFE79, 0xFE7A, 0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F,
+ /* 8 */ 0xFE80, 0xFE81, 0xFE82, 0xFE83, 0xFE84, 0xFE85, 0xFE86, 0xFE87,
+ 0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, 0xFE8D, 0xFE8E, 0xFE8F,
+ /* 9 */ 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95, 0xFE96, 0xFE97,
+ 0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E, 0xFE9F,
+ /* A */ 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7,
+ 0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF,
+ /* B */ 0xFEB0, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7,
+ 0xFEB8, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF,
+ /* C */ 0xFEC0, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7,
+ 0xFEC8, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, 0xFECD, 0xFECE, 0xFECF,
+ /* D */ 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4, 0xFED5, 0xFED6, 0xFED7,
+ 0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD, 0xFEDE, 0xFEDF,
+ /* E */ 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6, 0xFEE7,
+ 0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF,
+ /* F */ 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7,
+ 0xFEF8, 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0x0000,
+
+ // Table 10 (for high byte 0xFF)
+
+ /* 0 */ 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07,
+ 0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F,
+ /* 1 */ 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17,
+ 0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F,
+ /* 2 */ 0xFF20, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
+ 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
+ /* 3 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
+ 0xFF58, 0xFF59, 0xFF5A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F,
+ /* 4 */ 0xFF40, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
+ 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
+ /* 5 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
+ 0xFF58, 0xFF59, 0xFF5A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F,
+ /* 6 */ 0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67,
+ 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F,
+ /* 7 */ 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77,
+ 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F,
+ /* 8 */ 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87,
+ 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F,
+ /* 9 */ 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97,
+ 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F,
+ /* A */ 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7,
+ 0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF,
+ /* B */ 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7,
+ 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF,
+ /* C */ 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7,
+ 0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF,
+ /* D */ 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7,
+ 0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF,
+ /* E */ 0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7,
+ 0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF,
+ /* F */ 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7,
+ 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF,
+};
diff --git a/qemu/roms/openbios/fs/hfsplus/hfsp_volume.c b/qemu/roms/openbios/fs/hfsplus/hfsp_volume.c
new file mode 100644
index 000000000..2d624e23e
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/hfsp_volume.c
@@ -0,0 +1,323 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ *
+ * Code to acces the basic volume information of a HFS+ volume.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original work by 1996-1998 Robert Leslie <rob@mars.org>
+ * other work 2000 from Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: volume.c,v 1.21 2000/10/25 05:43:04 hasi Exp $
+ */
+
+#include "config.h"
+#include "libhfsp.h"
+#include "volume.h"
+#include "record.h"
+#include "btree.h"
+#include "blockiter.h"
+#include "os.h"
+#include "swab.h"
+#include "hfstime.h"
+
+
+/* Fill a given buffer with the given block in volume.
+ */
+int
+volume_readinbuf(volume * vol,void* buf, long block)
+{
+ UInt16 blksize_bits;
+ ASSERT( block < vol->maxblocks);
+
+ blksize_bits = vol->blksize_bits;
+ block += vol->startblock;
+ if( os_seek(vol->os_fd, block, blksize_bits) == block)
+ if( 1 == os_read(vol->os_fd, buf, 1, blksize_bits))
+ return 0;
+ return -1;
+}
+
+/* read multiple blocks into given memory.
+ *
+ * returns given pinter or NULL on failure.
+ */
+void*
+volume_readfromfork(volume* vol, void* buf,
+ hfsp_fork_raw* f, UInt32 block,
+ UInt32 count, UInt8 forktype, UInt32 fileId)
+{
+ blockiter iter;
+ char *cbuf = buf;
+
+ blockiter_init(&iter, vol, f, forktype, fileId);
+ if( blockiter_skip(&iter, block))
+ return NULL;
+
+ while( count > 0) {
+ --count;
+ if( volume_readinbuf(vol, cbuf, blockiter_curr(&iter)))
+ return NULL;
+ cbuf += vol->blksize;
+ if( count > 0 && blockiter_next(&iter))
+ return NULL;
+ }
+ return buf;
+}
+
+
+/* Read a raw hfsp_extent_rec from memory.
+ *
+ * return pointer right after the structure.
+ */
+void*
+volume_readextent(void *p, hfsp_extent_rec er)
+{
+ int i;
+ hfsp_extent *e;
+
+ for( i=0; i < 8; i++) {
+ e = &er[i];
+ e->start_block = bswabU32_inc(p);
+ e->block_count = bswabU32_inc(p);
+ }
+ return p;
+}
+
+/* Read a raw hfsp_fork from memory.
+ *
+ * return pointer right after the structure.
+ */
+void*
+volume_readfork(void *p, hfsp_fork_raw* f)
+{
+ f->total_size = bswabU64_inc(p);
+ f->clump_size = bswabU32_inc(p);
+ f->total_blocks = bswabU32_inc(p);
+
+ return volume_readextent(p, f->extents);
+}
+
+/* Read the volume from the given buffer and swap the bytes.
+ *
+ * ToDo: add more consitency checks.
+ */
+static int
+volume_readbuf(hfsp_vh* vh, char * p)
+{
+ if( (vh->signature = bswabU16_inc(p)) != HFSP_VOLHEAD_SIG)
+ HFSP_ERROR(-1, "This is not a HFS+ volume");
+
+ vh->version = bswabU16_inc(p);
+ vh->attributes = bswabU32_inc(p);
+ vh->last_mount_vers = bswabU32_inc(p);
+ vh->reserved = bswabU32_inc(p);
+ vh->create_date = bswabU32_inc(p);
+ vh->modify_date = bswabU32_inc(p);
+ vh->backup_date = bswabU32_inc(p);
+ vh->checked_date = bswabU32_inc(p);
+ vh->file_count = bswabU32_inc(p);
+ vh->folder_count = bswabU32_inc(p);
+ vh->blocksize = bswabU32_inc(p);
+ vh->total_blocks = bswabU32_inc(p);
+ vh->free_blocks = bswabU32_inc(p);
+ vh->next_alloc = bswabU32_inc(p);
+ vh->rsrc_clump_sz = bswabU32_inc(p);
+ vh->data_clump_sz = bswabU32_inc(p);
+ vh->next_cnid = bswabU32_inc(p);
+ vh->write_count = bswabU32_inc(p);
+ vh->encodings_bmp = bswabU64_inc(p);
+ memcpy(vh->finder_info, p, 32);
+ p += 32; // So finderinfo must be swapped later, ***
+ p = volume_readfork(p, &vh->alloc_file );
+ p = volume_readfork(p, &vh->ext_file );
+ p = volume_readfork(p, &vh->cat_file );
+ p = volume_readfork(p, &vh->attr_file );
+ volume_readfork(p, &vh->start_file );
+ return 0;
+ fail:
+ return -1;
+}
+
+/* Read the volume from the given block */
+static int
+volume_read(volume * vol, hfsp_vh* vh, UInt32 block)
+{
+ char buf[vol->blksize];
+
+ if( volume_readinbuf(vol, buf, block))
+ return -1;
+ return volume_readbuf(vh, buf);
+}
+
+/* Find out wether the volume is wrapped and unwrap it eventually */
+static int
+volume_read_wrapper(volume * vol, hfsp_vh* vh)
+{
+ UInt16 signature;
+ char buf[vol->blksize];
+ char *p = buf;
+ int ret;
+ UInt64 vol_size;
+
+ if( volume_readinbuf(vol, buf, 2) ) // Wrapper or volume header starts here
+ return -1;
+
+ signature = bswabU16_inc(p);
+ if( signature == HFS_VOLHEAD_SIG) { /* Wrapper */
+ UInt32 drAlBlkSiz; /* size (in bytes) of allocation blocks */
+ UInt32 sect_per_block; /* how may block build an hfs sector */
+ UInt16 drAlBlSt; /* first allocation block in volume */
+ UInt16 embeds, embedl; /* Start/lenght of embedded area in blocks */
+
+ p += 0x12; /* skip unneded HFS vol fields */
+ drAlBlkSiz = bswabU32_inc(p); /* offset 0x14 */
+ p += 0x4; /* skip unneded HFS vol fields */
+ drAlBlSt = bswabU16_inc(p); /* offset 0x1C */
+
+ p += 0x5E; /* skip unneded HFS vol fields */
+ signature = bswabU16_inc(p); /* offset 0x7C, drEmbedSigWord */
+ if( signature != HFSP_VOLHEAD_SIG)
+ HFSP_ERROR(-1, "This looks like a normal HFS volume");
+ embeds = bswabU16_inc(p);
+ embedl = bswabU16_inc(p);
+ sect_per_block = (drAlBlkSiz / HFSP_BLOCKSZ);
+ // end is absolute (not relative to HFS+ start)
+ vol->maxblocks = embedl * sect_per_block;
+ vol->startblock = drAlBlSt + embeds * sect_per_block;
+ /* Now we can try to read the embedded HFS+ volume header */
+ return volume_read(vol,vh,2);
+ }
+ else if( signature == HFSP_VOLHEAD_SIG) { /* Native HFS+ volume */
+ p = buf; // Restore to begin of block
+ ret = volume_readbuf(vh, p);
+ if( !ret ) {
+ /* When reading the initial partition we must use 512 byte blocks */
+ vol_size = (uint64_t)vh->blocksize * vh->total_blocks;
+ vol->maxblocks = vol_size / HFSP_BLOCKSZ;
+ }
+
+ return ret;
+ } else
+ HFSP_ERROR(-1, "Neither Wrapper nor native HFS+ volume header found");
+fail:
+ return -1;
+}
+
+
+/* Open the device, read and verify the volume header
+ (and its backup) */
+int
+volume_open( volume* vol, int os_fd )
+{
+ hfsp_vh backup; /* backup volume found at second to last block */
+ long sect_per_block;
+ int shift;
+
+ vol->blksize_bits = HFSP_BLOCKSZ_BITS;
+ vol->blksize = HFSP_BLOCKSZ;
+ vol->startblock = 0;
+ vol->maxblocks = 3;
+ /* this should be enough until we find the volume descriptor */
+ vol->extents = NULL; /* Thanks to Jeremias Sauceda */
+
+ btree_reset(&vol->catalog);
+ vol->os_fd = os_fd;
+
+ // vol->maxblocks = os_seek(vol->os_fd, -1, HFSP_BLOCKSZ_BITS);
+ // This wont work for /dev/... but we do not really need it
+
+ if( volume_read_wrapper(vol, &vol->vol))
+ return -1;
+ if( volume_read(vol, &backup, vol->maxblocks - 2))
+ return -1;
+
+ /* Now switch blksize from HFSP_BLOCKSZ (512) to value given in header
+ and adjust depend values accordingly, after that a block always
+ means a HFS+ allocation size */
+
+ /* Usually 4096 / 512 == 8 */
+ sect_per_block = vol->vol.blocksize / HFSP_BLOCKSZ;
+ shift = 0;
+ if( sect_per_block > 1) {
+ shift = 1;
+ while( sect_per_block > 2) {
+ sect_per_block >>=1;
+ shift++;
+ } /* shift = 3 */
+ }
+ vol -> blksize_bits += shift;
+ vol -> blksize = 1 << vol->blksize_bits;
+ vol -> startblock >>= shift;
+ vol -> maxblocks = vol->vol.total_blocks; /* cant calculate via shift ? */
+
+ if( btree_init_cat(&vol->catalog, vol, &vol->vol.cat_file))
+ return -1;
+
+ return 0;
+}
+
+/* Write back all data eventually cached and close the device */
+int
+volume_close(volume* vol)
+{
+ btree_close(&vol->catalog);
+ if( vol->extents) {
+ btree_close(vol->extents);
+ FREE(vol->extents);
+ }
+ return 0;
+}
+
+/* internal fucntion used to create the extents btree,
+ is called by inline function when needed */
+void
+volume_create_extents_tree(volume* vol)
+{
+ btree* result = (btree*) ALLOC(btree*, sizeof(btree));
+ if( !result)
+ HFSP_ERROR(ENOMEM, "No memory for extents btree");
+ if( !btree_init_extent(result, vol, &vol->vol.ext_file)) {
+ vol->extents = result;
+ return;
+ }
+ fail:
+ vol->extents = NULL;
+}
+
+/* Determine whether the volume is a HFS-plus volume */
+int
+volume_probe(int fd, long long offset)
+{
+ UInt16 *vol;
+ int ret = 0;
+
+ vol = (UInt16 *)malloc(2 * 1 << HFSP_BLOCKSZ_BITS);
+ os_seek_offset( fd, 2 * (1 << HFSP_BLOCKSZ_BITS) + offset );
+ os_read(fd, vol, 2, HFSP_BLOCKSZ_BITS);
+
+ if (__be16_to_cpu(vol[0]) == HFS_VOLHEAD_SIG &&
+ __be16_to_cpu(vol[0x3e]) == HFSP_VOLHEAD_SIG) {
+ ret = -1;
+ } else if (__be16_to_cpu(vol[0]) == HFSP_VOLHEAD_SIG) {
+ ret = -1;
+ }
+
+ free(vol);
+ return ret;
+}
+
diff --git a/qemu/roms/openbios/fs/hfsplus/include/apple.h b/qemu/roms/openbios/fs/hfsplus/include/apple.h
new file mode 100644
index 000000000..7ba836db6
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/include/apple.h
@@ -0,0 +1,111 @@
+/*
+ * libhfsp - library for reading and writing Macintosh HFS+ volumes
+ *
+ * This file contains defintions that are special for Apple.
+ * The names match the defintions found in Apple Header files.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original code 1996-1998 by Robert Leslie <rob@mars.rog>
+ * other work 2000 from Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: apple.h,v 1.2 2000/09/08 14:55:08 hasi Exp $
+ */
+
+typedef signed char Char;
+typedef unsigned char UChar;
+typedef signed char SInt8;
+typedef unsigned char UInt8;
+typedef signed short SInt16;
+typedef unsigned short UInt16;
+typedef signed long SInt32;
+typedef unsigned long UInt32;
+typedef unsigned long OSType;
+typedef unsigned long long UInt64;
+
+/* A point, normally used by Quickdraw,
+ * but found in Finderinformation, too
+ */
+typedef struct {
+ SInt16 v; /* vertical coordinate */
+ SInt16 h; /* horizontal coordinate */
+} Point;
+
+/* A rectancle, normally used by Quickdraw,
+ * but found in Finderinformation, too.
+ */
+typedef struct {
+ SInt16 top; /* top edge of rectangle */
+ SInt16 left; /* left edge */
+ SInt16 bottom; /* bottom edge */
+ SInt16 right; /* right edge */
+} Rect;
+
+/* Information about the location and size of a folder
+ * used by the Finder.
+ */
+typedef struct {
+ Rect frRect; /* folder's rectangle */
+ SInt16 frFlags; /* flags */
+ Point frLocation; /* folder's location */
+ SInt16 frView; /* folder's view */
+} DInfo;
+
+/* Extended folder information used by the Finder ...
+ */
+typedef struct {
+ Point frScroll; /* scroll position */
+ SInt32 frOpenChain; /* directory ID chain of open folders */
+ SInt16 frUnused; /* reserved */
+ SInt16 frComment; /* comment ID */
+ SInt32 frPutAway; /* directory ID */
+} DXInfo;
+
+/* Finder information for a File
+ */
+typedef struct {
+ OSType fdType; /* file type */
+ OSType fdCreator; /* file's creator */
+ SInt16 fdFlags; /* flags */
+ Point fdLocation; /* file's location */
+ SInt16 fdFldr; /* file's window */
+} FInfo;
+
+/* Extendend Finder Information for a file
+ */
+typedef struct {
+ SInt16 fdIconID; /* icon ID */
+ SInt16 fdUnused[4]; /* reserved */
+ SInt16 fdComment; /* comment ID */
+ SInt32 fdPutAway; /* home directory ID */
+} FXInfo;
+
+/* Flagvalues for FInfo and DInfo */
+# define HFS_FNDR_ISONDESK (1 << 0)
+# define HFS_FNDR_COLOR 0x0e
+# define HFS_FNDR_COLORRESERVED (1 << 4)
+# define HFS_FNDR_REQUIRESSWITCHLAUNCH (1 << 5)
+# define HFS_FNDR_ISSHARED (1 << 6)
+# define HFS_FNDR_HASNOINITS (1 << 7)
+# define HFS_FNDR_HASBEENINITED (1 << 8)
+# define HFS_FNDR_RESERVED (1 << 9)
+# define HFS_FNDR_HASCUSTOMICON (1 << 10)
+# define HFS_FNDR_ISSTATIONERY (1 << 11)
+# define HFS_FNDR_NAMELOCKED (1 << 12)
+# define HFS_FNDR_HASBUNDLE (1 << 13)
+# define HFS_FNDR_ISINVISIBLE (1 << 14)
+# define HFS_FNDR_ISALIAS (1 << 15)
diff --git a/qemu/roms/openbios/fs/hfsplus/include/blockiter.h b/qemu/roms/openbios/fs/hfsplus/include/blockiter.h
new file mode 100644
index 000000000..da3e480fd
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/include/blockiter.h
@@ -0,0 +1,59 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ *
+ * The iterator shown here iterates over the blocks of a fork.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original work by 1996-1998 Robert Leslie <rob@mars.org>
+ * other work 2000 from Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: blockiter.h,v 1.1 2000/10/10 11:14:05 hasi Exp $
+ */
+
+/* Structure of the blockiterator */
+typedef struct
+{
+ volume* vol; // volume we iterate over
+ UInt32 curr_block; // current, absolute block
+ UInt32 block; // relative block in current extent
+ UInt32 max_block; // Maximum allowed block
+ UInt32 fileId; // id of file we iterate over
+ int index; // 0 .. 7 in current extent
+ hfsp_extent* file; // original extent record from file
+ hfsp_extent* e; // current extentent under examination
+ UInt8 forktype; // type of fork we iterate over
+ UInt8 in_extent; // boolean 0 - in file extent
+ // 1 - in extents file
+ extent_record er; // record to iterate in extents file.
+} blockiter;
+
+/* Initialize iterator for a given fork */
+extern void blockiter_init(blockiter* b, volume* vol, hfsp_fork_raw* f,
+ UInt8 forktype, UInt32 fileId);
+
+/* find next block of the fork iterating over */
+extern int blockiter_next(blockiter *b);
+
+/* skip the indicated number of blocks */
+extern int blockiter_skip(blockiter *b, UInt32 skip);
+
+/* return current block */
+static inline UInt32 blockiter_curr(blockiter *b)
+{
+ return b->e->start_block + b->block;
+}
diff --git a/qemu/roms/openbios/fs/hfsplus/include/btree.h b/qemu/roms/openbios/fs/hfsplus/include/btree.h
new file mode 100644
index 000000000..46ac8501f
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/include/btree.h
@@ -0,0 +1,50 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes.
+ *
+ * The fucntions are used to handle the various forms of btrees
+ * found on HFS+ volumes.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original 1996-1998 Robert Leslie <rob@mars.org>
+ * Additional work by Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: btree.h,v 1.10 2000/10/25 05:43:04 hasi Exp $
+ */
+
+/** Intialize catalog btree, so that btree_close can safely be called. */
+extern void btree_reset(btree* bt);
+
+/** Intialize catalog btree */
+extern int btree_init_cat(btree* bt, volume* vol, hfsp_fork_raw* fork);
+
+/** Intialize extents btree */
+extern int btree_init_extent(btree* bt, volume* vol, hfsp_fork_raw* fork);
+
+/** close the btree and free any resources */
+extern void btree_close(btree* bt);
+
+/* Read node at given index */
+extern node_buf* btree_node_by_index(btree* bt, UInt16 index);
+
+/* returns pointer to key given by index in current node */
+extern void* btree_key_by_index(btree* bt, node_buf* buf, UInt16 index);
+
+#ifdef DEBUG
+ /* Dump all the btree information to stdout */
+ extern void btree_print(btree* bt);
+#endif
diff --git a/qemu/roms/openbios/fs/hfsplus/include/hfs.h b/qemu/roms/openbios/fs/hfsplus/include/hfs.h
new file mode 100644
index 000000000..5b0cbb490
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/include/hfs.h
@@ -0,0 +1,32 @@
+/*
+ * libhfsp - library for reading and writing Macintosh HFS+ volumes
+ *
+ * This file includes definitions for access to old HFS structures.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original code 1996-1998 by Robert Leslie <rob@mars.rog>
+ * other work 2000 from Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: hfs.h,v 1.1.1.1 2000/07/25 10:33:40 kkaempf Exp $
+ */
+
+
+#define HFS_BLOCKSZ 512
+ /* A sector for Apple is always 512 bytes */
+#define HFS_BLOCKSZ_BITS 9 /* 1<<9 == 512 */
+#define HFS_VOLHEAD_SIG 0x4244 /* 'BD' */
diff --git a/qemu/roms/openbios/fs/hfsplus/include/hfsp.h b/qemu/roms/openbios/fs/hfsplus/include/hfsp.h
new file mode 100644
index 000000000..e916473c6
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/include/hfsp.h
@@ -0,0 +1,305 @@
+/*
+ * libhfsp - library for reading and writing Macintosh HFS+ volumes
+ *
+ * This file includes definitions for the structures found on
+ * HFS+ Volumes. The structures are further wrapped by struct
+ * found in libhfsp.h. fucntions on those enhanced structures
+ * are found in files mentioned in comments below.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original code 1996-1998 by Robert Leslie <rob@mars.rog>
+ * other work 2000 from Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: hfsp.h,v 1.17 2000/10/20 06:16:52 hasi Exp $
+ */
+
+#define HFSP_BLOCKSZ 512 /* A sector for Apple is always 512 bytes */
+#define HFSP_BLOCKSZ_BITS 9 /* 1<<9 == 512 */
+#define HFSP_VOLHEAD_SIG 0x482B /* 'H+' */
+
+/* HFS+ includes POSIX permissions , although marked as reserved they will be
+ * used as such. Is ignored by MacOS 8-9 but probably not by MacOS X.
+ */
+typedef struct {
+ UInt32 owner;
+ UInt32 group;
+ UInt32 mode;
+ UInt32 dev;
+} hfsp_perm;
+
+/* A single contiguous area (fragment) of a file */
+typedef struct {
+ UInt32 start_block;
+ UInt32 block_count;
+} hfsp_extent;
+
+/* A file may contain up to 8 normale extents, all other
+ are found in some extra extent area */
+typedef hfsp_extent hfsp_extent_rec[8];
+
+/* Information for a "Fork" in a file
+ * Forks are the "usual" DATA and RSRC forks or special files
+ * (e.g. the Volume Bitmap)
+ */
+typedef struct {
+ UInt64 total_size; // logical size
+ UInt32 clump_size; // number of bytes to preallocate
+ UInt32 total_blocks;
+ hfsp_extent_rec extents; // initial (8) extents
+} hfsp_fork_raw;
+
+/* HFS+ Volume Header
+ * Always found at block 2 of the disk, a copy is stored
+ * at the second to last block of the disk.
+ */
+typedef struct hfsp_vh {
+ UInt16 signature; // must be HFSPLUS_VOLHEAD_SIG 'H+'
+ UInt16 version; // currently 4, ignored
+ UInt32 attributes; // See bit constants below
+ UInt32 last_mount_vers;
+ // Use a registered creator code here (what do we use ?)
+ // Mac OS uses '8.10' well
+ UInt32 reserved;
+
+ UInt32 create_date; // local time !
+ UInt32 modify_date; // GMT (?)
+ UInt32 backup_date; // GMT (?)
+ UInt32 checked_date; // GMT (?) fsck ?
+
+ UInt32 file_count;
+ // not including special files but including DATA and RSRC forks
+ UInt32 folder_count; // excluding the root folder
+
+ UInt32 blocksize;
+ // must be multiple of HFSPLUS_SECTOR_SIZE,
+ // should be a multiple of 4k for harddisk
+ UInt32 total_blocks;
+ UInt32 free_blocks;
+ // The total number of unused allocation blocks on the disk.
+
+ UInt32 next_alloc;
+ // hint wher to search for next allocation blocks
+ UInt32 rsrc_clump_sz;
+ // default clump size for rsrc forks
+ UInt32 data_clump_sz;
+ // default clump size for data forks
+ UInt32 next_cnid;
+ // next unused catalog id
+ UInt32 write_count;
+ // increment on every mount (and write ?)
+ UInt64 encodings_bmp;
+ // for every encoding used on the disk a bit is set
+ // ignored but eventually must be cared for
+ Char finder_info[32];
+ hfsp_fork_raw alloc_file;
+ // stores bitmap of use/free blocks
+ hfsp_fork_raw ext_file;
+ // stores oferflow extents
+ hfsp_fork_raw cat_file;
+ // This contains the root directory
+ hfsp_fork_raw attr_file;
+ hfsp_fork_raw start_file;
+ // a special startup file may be described here (used by ?)
+} hfsp_vh;
+
+/* HFS+ volume attributes */
+/* 0-6 reserved, may be used in memory only */
+#define HFSPLUS_VOL_RESERVED1 0x000000FF
+#define HFSPLUS_VOL_HARDLOCK 0x00000080 // Used in Memory by finder only
+#define HFSPLUS_VOL_UNMNT 0x00000100
+ // clear this bit when mounting, set as last step of unmounting
+ // This is checked by (slower) ROM code
+#define HFSPLUS_VOL_SPARE_BLK 0x00000200
+#define HFSPLUS_VOL_NOCACHE 0x00000400
+ // in case of RAM or ROM disk (try a HFS+ Ramdisk :)
+#define HFSPLUS_VOL_INCNSTNT 0x00000800
+ // Reverse meaning as of HFSPLUS_VOL_UNMNT
+ // This is checked by (faster) Mac OS code
+/* 12-14 reserved */
+#define HFSPLUS_VOL_RESERVED2 0x00007000
+#define HFSPLUS_VOL_SOFTLOCK 0x00008000
+#define HFSPLUS_VOL_RESERVED3 0xFFFF0000
+
+/* HFS+ Btree node descriptor */
+typedef struct {
+ UInt32 next; /* pointer to next node of this kind, or 0 */
+ UInt32 prev; /* pointer to previous node of this kind, or 0 */
+ UInt8 kind; /* see below */
+ UInt8 height; /* root node starts with 0 */
+ UInt16 num_rec; /* number of records in this node */
+ UInt16 reserved; /* fill up to 4 byte alignment */
+} btree_node_desc;
+
+/* HFS+ Btree Node types */
+#define HFSP_NODE_NDX 0x00
+#define HFSP_NODE_HEAD 0x01
+#define HFSP_NODE_MAP 0x02
+#define HFSP_NODE_LEAF 0xFF
+
+#define HFSP_CATALOG_MIN_NODE_SIZE 0x1000
+#define HFSP_ATTRMIN_DOE_SIZE 0x1000
+
+/* The record offsets are found at the end of the fork
+ * containing the Btree */
+
+typedef UInt16 btree_record_offset;
+
+typedef struct {
+ UInt16 depth;
+ // equal to height of btree_node_desc
+ UInt32 root;
+ // root node of the hierarchy
+ UInt32 leaf_count;
+ UInt32 leaf_head;
+ UInt32 leaf_tail;
+ UInt16 node_size;
+ // node size of _all_ nodes in this fork
+ UInt16 max_key_len;
+ UInt32 node_count;
+ // count of all (free and used) nodes in tree
+ UInt32 free_nodes;
+ UInt16 reserved1;
+ UInt32 clump_size;
+ // ignored my MacOS used by ?
+ UInt8 btree_type;
+ // always 0 for HFS+
+ UInt8 reserved2;
+ UInt32 attributes;
+ // see below
+ UInt32 reserved3[16];
+} btree_head;
+
+/* BTree attributes */
+#define HFSPLUS_BAD_CLOSE 0x01
+ // Btree was not properly closed and should be checked
+ // not used for HFS+ but reserved
+#define HFSPLUS_TREE_BIGKEYS 0x02
+ // always set for HFS+
+#define HFSPLUS_TREE_VAR_NDXKEY_SIZE 0x04
+ // use variable length index nodes, always set for catalog btree,
+ // always cleared for extents btree.
+
+#define HFSPLUS_TREE_UNUSED 0xFFFFFFF8
+
+/* Some special File ID numbers */
+#define HFSP_POR_CNID 1 /* Parent Of the Root */
+#define HFSP_ROOT_CNID 2 /* ROOT directory */
+#define HFSP_EXT_CNID 3 /* EXTents B-tree */
+#define HFSP_CAT_CNID 4 /* CATalog B-tree */
+#define HFSP_BAD_CNID 5 /* BAD blocks file */
+#define HFSP_ALLOC_CNID 6 /* ALLOCation file */
+#define HFSP_START_CNID 7 /* STARTup file */
+#define HFSP_ATTR_CNID 8 /* ATTRibutes file */
+#define HFSP_EXCH_CNID 15 /* ExchangeFiles temp id */
+#define HFPS_MIN_CNID 15 /* Minimum expected value */
+
+/* Unicode String */
+typedef struct {
+ UInt16 strlen;
+ UInt16 name[255]; // unicode charcters
+} hfsp_unistr255;
+
+/* HFS+ catalog entry key */
+typedef struct {
+ UInt16 key_length; /* excluding length */
+ UInt32 parent_cnid;
+ hfsp_unistr255 name;
+} hfsp_cat_key;
+
+/* HFS+ exnteds entry key */
+typedef struct {
+ UInt16 key_length; /* excluding length */
+ UInt8 fork_type; /* Seee below */
+ UInt8 filler;
+ UInt32 file_id;
+ UInt32 start_block;
+} hfsp_extent_key;
+
+#define HFSP_EXTENT_DATA 0x00
+#define HFSP_EXTENT_RSRC 0xFF
+
+/* The key is followed by a record, an index or some other data */
+
+/* The types of these records are defined as follows */
+
+#define HFSP_FOLDER 0x0001 // entry fo a Folder
+#define HFSP_FILE 0x0002 // entry for a File
+#define HFSP_FOLDER_THREAD 0x0003
+ // Like '.' in unix, identifies the folder by its id, only
+#define HFSP_FILE_THREAD 0x0004
+ // Im unsure if this is used by HFS+, too
+
+/* HFS+ folder data (part of an hfsp_cat_entry) */
+typedef struct {
+ UInt16 flags; /* no flags defined yet */
+ UInt32 valence; /* Numer of files and folders contained in folder */
+ UInt32 id;
+ UInt32 create_date; // GMT
+ UInt32 content_mod_date; // GMT
+ UInt32 attribute_mod_date; // GMT
+ UInt32 access_date; // GMT
+ UInt32 backup_date; // GMT
+ hfsp_perm permissions;
+ DInfo user_info;
+ DXInfo finder_info;
+ UInt32 text_encoding;
+ // hint fo the finder what encoding to use, unused here
+ UInt32 reserved;
+} hfsp_cat_folder;
+
+/* HFS+ file data (part of a cat_entry) */
+typedef struct {
+ UInt16 flags; /* See below */
+ UInt32 reserved1;
+ UInt32 id;
+ UInt32 create_date;
+ UInt32 content_mod_date;
+ UInt32 attribute_mod_date;
+ UInt32 access_date;
+ UInt32 backup_date;
+ hfsp_perm permissions;
+ FInfo user_info;
+ FXInfo finder_info;
+ UInt32 text_encoding;
+ UInt32 reserved2;
+
+ hfsp_fork_raw data_fork;
+ hfsp_fork_raw res_fork;
+} hfsp_cat_file;
+
+/* File attribute bits */
+#define HFSP_FILE_LOCKED 0x0001
+#define HFSP_THREAD_EXISTS 0x0002 /* Always set in HFS+ */
+
+/* HFS+ catalog thread (part of a cat_entry) */
+typedef struct {
+ UInt16 reserved;
+ UInt32 parentID;
+ hfsp_unistr255 nodeName;
+} hfsp_cat_thread;
+
+
+/* A data record in the catalog tree */
+typedef struct {
+ UInt16 type;
+ union {
+ hfsp_cat_folder folder;
+ hfsp_cat_file file;
+ hfsp_cat_thread thread;
+ } u;
+} hfsp_cat_entry;
diff --git a/qemu/roms/openbios/fs/hfsplus/include/hfstime.h b/qemu/roms/openbios/fs/hfsplus/include/hfstime.h
new file mode 100644
index 000000000..bb6bd4a6e
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/include/hfstime.h
@@ -0,0 +1,34 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>^
+ * Original 1996-1998 Robert Leslie <rob@mars.org>
+ * other work 2000 from Brad Boyer (flar@pants.nu)
+ *
+ * The HFS+ dates are stored as UInt32 containing the number of seconds since
+ * midnight, January 1, 1904, GMT. This is slightly different from HFS,
+ * where the value represents local time. A notable exception is the
+ * creationdate !. Linux uses times in GMT starting at January 1, 1970
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: hfstime.h,v 1.2 2000/10/19 13:33:38 hasi Exp $
+ */
+
+ /* The number of seconds between 1.1.1904 and 1.1.1970 */
+#define HFSPTIMEDIFF 2082844800U
+
+ /* return the given apple time as UNIX time */
+extern char* get_atime(UInt32 atime);
diff --git a/qemu/roms/openbios/fs/hfsplus/include/libhfsp.h b/qemu/roms/openbios/fs/hfsplus/include/libhfsp.h
new file mode 100644
index 000000000..912cfbd05
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/include/libhfsp.h
@@ -0,0 +1,201 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 2000 Klaus Halfmann (khalfmann@libra.de)
+ * Original work by 1996-1998 Robert Leslie (rob@mars.org)
+ *
+ * This file defines constants,structs etc needed for this library.
+ * Everything found here is usually not related to Apple defintions.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: libhfsp.h,v 1.17 2000/10/20 06:16:52 hasi Exp $
+ */
+
+# include "apple.h"
+# include "hfs.h"
+# include "hfsp.h"
+
+/* Last error is eventually found here */
+extern const char *hfsp_error;
+
+# define HFSP_ERROR(code, str) \
+ do { hfsp_error = (str), errno = (code); goto fail; } while (0)
+
+# ifdef DEBUG
+# define ASSERT(cond) do { if (! (cond)) abort(); } while (0)
+# else
+# define ASSERT(cond) /* nothing */
+# endif
+
+# define SIZE(type, n) ((size_t) (sizeof(type) * (n)))
+# define ALLOC(type, n) ((type *) malloc(SIZE(type, n)))
+# define ALLOCX(type, n) ((n) ? ALLOC(type, n) : (type *) 0)
+# define FREE(ptr) ((ptr) ? (void) free((void *) ptr) : (void) 0)
+
+# define REALLOC(ptr, type, n) \
+ ((type *) ((ptr) ? realloc(ptr, SIZE(type, n)) : malloc(SIZE(type, n))))
+# define REALLOCX(ptr, type, n) \
+ ((n) ? REALLOC(ptr, type, n) : (FREE(ptr), (type *) 0))
+
+# define BMTST(bm, num) \
+ (((const byte *) (bm))[(num) >> 3] & (0x80 >> ((num) & 0x07)))
+# define BMSET(bm, num) \
+ (((byte *) (bm))[(num) >> 3] |= (0x80 >> ((num) & 0x07)))
+# define BMCLR(bm, num) \
+ (((byte *) (bm))[(num) >> 3] &= ~(0x80 >> ((num) & 0x07)))
+
+# define STRINGIZE(x) #x
+# define STR(x) STRINGIZE(x)
+
+/* used by internal routines to specify the open modes */
+# define HFSP_MODE_RDONLY 0
+# define HFSP_MODE_RDWR 1
+# define HFSP_MODE_ANY 2
+
+/* Signatures registered with Apple to identify this driver */
+ /* Identifies the userland implementation */
+# define HPLS_SIGNATURE 0x482B4C58 // 'H+LX'
+ /* Identifies the kernel module by Brad Boyer (flar@pants.nu) */
+# define HPLS_SIGRES1 0x482B4C78 // 'H+Lx'
+ /* not jet in use ... */
+# define HPLS_SIGRES2 0x482B6C78 // 'H+lx'
+ /* Signature used by Apple */
+# define HPAPPLE_SIGNATURE 0x382e3130 // '8.10'
+
+/* Version used for this implementation of HFS+. This is not related
+ * to the VERSION file found at the top-level of this package,
+ * but designates the version of the low level code */
+#define HPLS_VERSION 1 /* must fit in a short */
+
+
+/* Othe Signatures may follow for informational purpos */
+
+/* prototype for key comparing functions. */
+typedef int (*hfsp_key_compare) (void* key1, void* key2);
+
+/* prototype for key reading (necessary for byte swapping) */
+typedef void* (*hfsp_key_read) (void* p, void* key);
+
+struct volume; /* foreward declaration for btree needed */
+
+/* Structures for a node cache. The cache is an array
+ * with linear search. (So making it to big may make
+ * things slower). It is searched in a round robin
+ * fashion.
+ */
+
+typedef struct
+{
+ UInt32 priority;
+ // as lower this number as higher the priority.
+ // decremetned on any sucessfull usage
+ // incremented else, intial value height*DEPTHFACTOR
+ UInt16 index; // of node in fork
+ // 0 means empty, since first node is node header
+ // contents of node in original byte order
+ UInt16 flags; // like DIRTY etc.
+} node_entry;
+
+typedef struct
+{
+ UInt32 index; // duplicate of above
+ btree_node_desc desc; // header of node
+ char node[0]; // actual node_size
+ // contents of node in original byte order
+} node_buf;
+
+typedef struct
+{
+ int size; // number of nodes in the cache
+ int currindex; // round robin index
+ int nodebufsize; // size of complete node_buf, including node
+ node_entry *entries;
+ char *buffers; // actually *node_buf
+} node_cache;
+
+typedef struct
+{
+ struct volume* vol; /* pointer to volume this tree is part of */
+ hfsp_fork_raw* fork; /* pointer to fork this tree is part of */
+ UInt32 cnid; /* (pseudo) file id for the fork */
+ hfsp_key_compare kcomp;
+ /* function used for key compare in _this_ btree */
+ hfsp_key_read kread;
+ /* fucntion used to read a key int _this_ btree */
+ btree_head head;
+
+ UInt16 blkpernode;
+ /* Number of volume blocks per node (usually 1-4) */
+ node_cache cache;
+ /* Warning all functions of btrees and records may modify
+ the following values ! */
+ // UInt16 node_index; /* index of node in fork */
+ // btree_node_desc node; /* current node under examination */
+ // char* buf; /* buf with size of a node */
+} btree;
+
+/* Function on btrees are defined in btree.h */
+
+/* A Wrapper around the raw hfs+ volume header for additional information
+ * needed by this library.
+ */
+
+typedef struct volume
+{
+ int os_fd; /* OS dependend reference to device */
+ UInt16 blksize_bits; /* blocksize of device = 1 << blksize_bits */
+ UInt16 filler;
+ UInt32 blksize; /* always 1 << blksize_bits */
+ UInt32 startblock;
+ /* Offset from physical to logical blocks,
+ eventually intodruced by HFS wrapper */
+ UInt32 maxblocks; /* maximum number of blocks in device */
+ // UInt32 currblock; /* value of current block, to cache blocks */
+ hfsp_vh vol; /* raw volume data */
+ // void* blockbuf; /* (single) buffer for fetching one block */
+ /* Buffer has double size of blksize to allow cross block reading */
+
+ btree* extents; /* is NULL by default and intialized when needed */
+ btree catalog; /* This is always neeeded */
+} volume;
+
+/* Functions on volumes are defined in volume.h */
+
+typedef struct { // may not be used as found here
+ btree* tree; // tree where this record is contained in.
+ UInt16 node_index; /* index of record in btree */
+ UInt16 keyind; /* index of current key in btree */
+ hfsp_cat_key key; /* current key */
+ UInt32 child; /* child node belonging to this key */
+} index_record;
+
+typedef struct {
+ btree* tree; // tree where this record is contained in.
+ UInt16 node_index; /* index of record in btree */
+ UInt16 keyind; /* index of current key in btree */
+ hfsp_extent_key key; /* current key */
+ hfsp_extent_rec extent; /* The payload carried around */
+} extent_record;
+
+typedef struct {
+ btree* tree; // tree where this record is contained in.
+ UInt16 node_index; /* index of record in btree */
+ UInt16 keyind; /* index of current key in btree */
+ hfsp_cat_key key; /* current key */
+ hfsp_cat_entry record; /* current record */
+} record;
+
+/* Functions on records are defined in record.h */
diff --git a/qemu/roms/openbios/fs/hfsplus/include/record.h b/qemu/roms/openbios/fs/hfsplus/include/record.h
new file mode 100644
index 000000000..6454f552a
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/include/record.h
@@ -0,0 +1,80 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes.
+ *
+ * a record contains a key and a folder or file and is part
+ * of a btree.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original 1996-1998 Robert Leslie <rob@mars.org>
+ * Additional work by Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: record.h,v 1.10 2000/10/01 17:08:05 hasi Exp $
+ */
+
+/* Compare two cat_keys ... */
+extern int record_key_compare(void* k1, void* k2);
+
+/* Compare two extent_keys ... */
+extern int record_extent_key_compare(void* k1, void* k2);
+
+/* read a catalog key into a given buffer */
+extern void* record_readkey(void* p, void* buf);
+
+/* read an extent key into a given buffer */
+extern void* record_extent_readkey(void* p, void* buf);
+
+/* intialize the record to the first record of the tree
+ * which is (per design) the root node.
+ */
+extern int record_init_root(record* r, btree* tree);
+
+/* intialize the record to the folder given by cnid.
+ */
+extern int record_init_cnid(record* r, btree* tree, UInt32 cnid);
+
+/* intialize the record to the first record of the parent.
+ */
+extern int record_init_parent(record* r, record* parent);
+
+/* intialize the record by searching for the given string in the given folder.
+ *
+ * parent and r may be the same.
+ */
+extern int record_init_string_parent(record* r, record* parent, char* key);
+
+/* move record up in folder hierarchy (if possible) */
+extern int record_up(record* r);
+
+/* move record foreward to next entry.
+ *
+ * In case of an error the value of *r is undefined !
+ */
+extern int record_next(record* r);
+
+/* intialize the extent_record to the extent identified by
+ * a given file */
+extern int record_init_file(extent_record* r, btree* tree,
+ UInt8 forktype, UInt32 fileId, UInt32 blockindex);
+
+/* move foreward to next entent record. */
+extern int record_next_extent(extent_record *r);
+
+#ifdef DEBUG
+ /* Dump all the record information to stdout */
+ extern void record_print(record* r);
+#endif
diff --git a/qemu/roms/openbios/fs/hfsplus/include/swab.h b/qemu/roms/openbios/fs/hfsplus/include/swab.h
new file mode 100644
index 000000000..c424008ee
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/include/swab.h
@@ -0,0 +1,64 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ *
+ * Copyright (C) 2000 Klaus Halfmann <klaus.halfmann@feri.de>
+ * Original work 1996-1998 Robert Leslie <rob@mars.org>
+ *
+ * This file defines some byte swapping function. I did not find this
+ * in any standard or linux way.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: swab.h,v 1.1.1.1 2002/03/05 19:50:29 klaus Exp $
+ */
+
+#include "config.h"
+#include "libc/byteorder.h"
+
+ /* basic fuction:
+ value = swab_inc(ptr);
+ ptr is afterwards incremented by sizeof(value)
+ */
+
+#ifndef CONFIG_BIG_ENDIAN
+
+#define bswabU16(val) __bswap16(val)
+
+#define bswabU16_inc(ptr) (__extension__ ({ UInt16 v=__bswap16(*((UInt16*) (ptr))); ptr+=sizeof(UInt16);v;}))
+#define bswabU32_inc(ptr) (__extension__ ({ UInt32 v=__bswap32(*((UInt32*) (ptr))); ptr+=sizeof(UInt32);v;}))
+#define bswabU64_inc(ptr) (__extension__ ({ UInt64 v=__bswap64(*((UInt64*) (ptr))); ptr+=sizeof(UInt64);v;}))
+
+#define bstoreU16_inc(ptr, val) do {(*((UInt16*) (ptr))) = __bswap16(val); ptr+=sizeof(UInt16);} while (0)
+#define bstoreU32_inc(ptr, val) do {(*((UInt32*) (ptr))) = __bswap32(val); ptr+=sizeof(UInt32);} while (0)
+#define bstoreU64_inc(ptr, val) do {(*((UInt64*) (ptr))) = __bswap64(val); ptr+=sizeof(UInt64);} while (0)
+
+#else // BYTE_ORDER == BIG_ENDIAN
+
+#define bswabU16(val) val
+
+#define bswabU16_inc(ptr) (__extension__ ({ UInt16 v=(*((UInt16*) (ptr))); ptr+=sizeof(UInt16);v;}))
+#define bswabU32_inc(ptr) (__extension__ ({ UInt32 v=(*((UInt32*) (ptr))); ptr+=sizeof(UInt32);v;}))
+#define bswabU64_inc(ptr) (__extension__ ({ UInt64 v=(*((UInt64*) (ptr))); ptr+=sizeof(UInt64);v;}))
+
+#define bstoreU16_inc(ptr, val) do {(*((UInt16*) (ptr))) = val; ptr+=sizeof(UInt16);} while (0)
+#define bstoreU32_inc(ptr, val) do {(*((UInt32*) (ptr))) = val; ptr+=sizeof(UInt32);} while (0)
+#define bstoreU64_inc(ptr, val) do {(*((UInt64*) (ptr))) = val; ptr+=sizeof(UInt64);} while (0)
+
+#endif
+
+/* for the sake of compleetness and readability */
+#define bswabU8_inc(ptr) (__extension__ ({ UInt8 v=(*((UInt8*) (ptr))); ptr+=sizeof(UInt8);v;}))
+#define bstoreU8_inc(ptr,val) do {(*((UInt8*) (ptr))) = val; ptr+=sizeof(UInt8);} while (0)
diff --git a/qemu/roms/openbios/fs/hfsplus/include/unicode.h b/qemu/roms/openbios/fs/hfsplus/include/unicode.h
new file mode 100644
index 000000000..e7c86f78a
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/include/unicode.h
@@ -0,0 +1,28 @@
+/*
+ * linux/fs/hfsplus/unicode.c
+ *
+ * Copyright (C) 1999-2000 Brad Boyer (flar@pants.nu)
+ * This file may be distributed under the terms of the GNU Public License.
+ *
+ * The routines found here convert hfs-unicode string into ascii Strings
+ * and vice versa. And the correct comparison between Strings.
+ */
+
+/* convert the asci string astr into a unicode string given by ustr.
+ *
+ * returns actual length of convertet string.
+ */
+
+int unicode_asc2uni(hfsp_unistr255 *ustr, const char *astr);
+
+/* Convert an unicode string ustr to a ascii string astr of given maximum len
+ *
+ * returns actual length of convertet string.
+ */
+
+int unicode_uni2asc(char *astr, const hfsp_unistr255 *ustr, int maxlen);
+
+/* similar to strcmp for unicode, pascal strings */
+
+SInt32 fast_unicode_compare (const hfsp_unistr255 *ustr1,
+ const hfsp_unistr255 *ustr2);
diff --git a/qemu/roms/openbios/fs/hfsplus/include/volume.h b/qemu/roms/openbios/fs/hfsplus/include/volume.h
new file mode 100644
index 000000000..19be05500
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/include/volume.h
@@ -0,0 +1,87 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>^
+ * Original 1996-1998 Robert Leslie <rob@mars.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: volume.h,v 1.11 2000/10/17 05:58:46 hasi Exp $
+ */
+
+#ifndef _H_VOLUME
+#define _H_VOLUME
+
+/* Open the device, read and verify the volume header
+ (and its backup) */
+extern int volume_open(volume* vol, int os_fd);
+
+/* Write back all data eventually cached and close the device. */
+extern int volume_close(volume* vol);
+
+/* read multiple blocks into given memory.
+ *
+ * returns given pointer or NULL on failure.
+ */
+extern void* volume_readfromfork(volume* vol, void* buf,
+ hfsp_fork_raw* f, UInt32 block,
+ UInt32 count, UInt8 forktype, UInt32 fileId);
+
+/* Fill a given buffer with the given block in volume.
+ */
+int volume_readinbuf(volume * vol,void* buf, long block);
+
+/* invalidat cache hold in volume, will be removed when
+ * caching strategy is clear to me. */
+/*
+extern inline void volume_invalidate_cache(volume* vol)
+{
+ vol -> currblock = (UInt32) -1;
+}
+*/
+
+/* Check in Allocation file if given block is allocated. */
+extern int volume_allocated(volume* v, UInt32 block);
+
+/* Read a raw hfsp_extent_rec from memory. */
+extern void* volume_readextent(void *p, hfsp_extent_rec er);
+
+/* Read fork information from raw memory */
+extern void* volume_readfork(void *p, hfsp_fork_raw* f);
+
+/* internal function used to create the extents btree,
+ is called by following inline fucntion when needed */
+extern void volume_create_extents_tree(volume* vol);
+
+/* accessor for entends btree, is created on demand */
+static inline btree* volume_get_extents_tree(volume* vol) {
+ if (!vol->extents)
+ volume_create_extents_tree(vol);
+ return vol->extents;
+}
+
+/* Determine whether the volume is a HFS-plus volume */
+int volume_probe(int fd, long long offset);
+
+#ifdef DEBUG
+ /* Print raw fork information to stdout */
+ void volume_print_fork(hfsp_fork_raw* f);
+ /* Dump all the volume information to stdout */
+ void volume_print(hfsp_vh* vol);
+#endif
+
+
+
+#endif /* _H_VOLUME */
diff --git a/qemu/roms/openbios/fs/hfsplus/libhfsp.c b/qemu/roms/openbios/fs/hfsplus/libhfsp.c
new file mode 100644
index 000000000..af1cde6a9
--- /dev/null
+++ b/qemu/roms/openbios/fs/hfsplus/libhfsp.c
@@ -0,0 +1,29 @@
+/*
+ * libhfsp - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * Thi file contains utitlity fucntions to manage the features of
+ * the hfs+ library.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: libhfsp.c,v 1.1.1.1 2000/07/25 10:33:40 kkaempf Exp $
+ */
+
+#include "config.h"
+#include "libhfsp.h"
+
+const char *hfsp_error = "no error"; /* static error string */