Commit yaboot 1.3.4-pre1.
git-archimport-id: erbenson@alaska.net--public/yaboot--devel--1.3--patch-5
# tag: automatic-ChangeLog--erbenson@alaska.net--public/yaboot--devel--1.3
#
+2002-03-25 15:13:19 GMT Ethan Benson <erbenson@alaska.net> patch-5
+
+ Summary:
+ Commit yaboot 1.3.4-pre1
+ Revision:
+ yaboot--devel--1.3--patch-5
+
+ Commit yaboot 1.3.4-pre1.
+
+ new files:
+ include/xfs/.arch-ids/=id include/xfs/.arch-ids/xfs.h.id
+ include/.arch-ids/errors.h.id second/.arch-ids/fs_xfs.c.id
+ .arch-ids/Config.id include/xfs/xfs.h include/errors.h
+ second/fs_xfs.c Config
+
+ removed files:
+ include/.arch-ids/gui.h.id include/.arch-ids/video.h.id
+ second/gui/.arch-ids/=id second/gui/.arch-ids/colormap.c.id
+ second/gui/.arch-ids/effects.c.id
+ second/gui/.arch-ids/pcx.c.id second/gui/.arch-ids/video.c.id
+ include/gui.h include/video.h second/gui/colormap.c
+ second/gui/effects.c second/gui/pcx.c second/gui/video.c
+
+ modified files:
+ ChangeLog Makefile THANKS changelog include/file.h
+ include/fs.h include/prom.h include/string.h include/yaboot.h
+ lib/malloc.c second/cfg.c second/file.c second/fs.c
+ second/fs_ext2.c second/fs_iso.c second/fs_of.c
+ second/fs_reiserfs.c second/partition.c second/prom.c
+ second/yaboot.c util/addnote.c ybin/ybin
+
+ new directories:
+ include/xfs/.arch-ids include/xfs
+
+ removed directories:
+ second/gui/.arch-ids second/gui
+
+
2002-03-25 14:50:10 GMT Ethan Benson <erbenson@alaska.net> patch-4
Summary:
--- /dev/null
+# Configuration variables, y == enabled n == disabled
+
+# Enable text color configurability: the fgcolor= and bgcolor= config
+# options (see yaboot.conf(5))
+#
+CONFIG_COLOR_TEXT := y
+
+# Enable colormap setup. Required on PowerMacs for text coloring to
+# work right.
+#
+CONFIG_SET_COLORMAP := y
+
+# Enable md5 passwords, allows value of password= to be an MD5 hash as
+# well as cleartext. When set to n only cleartext passwords are accepted.
+#
+USE_MD5_PASSWORDS := y
+
+# Filesystem support
+#
+# Enable SGI XFS
+#
+CONFIG_FS_XFS := y
+
+# Enable ReiserFS
+#
+CONFIG_FS_REISERFS := y
+
+# Local Variables:
+# mode: makefile
+# End:
-## Configuration section
+## Setup
-VERSION = 1.3.3
-# Debug mode (verbose)
+include Config
+
+VERSION = 1.3.4pre1
+# Debug mode (spam/verbose)
DEBUG = 0
+# make install vars
ROOT =
PREFIX = usr/local
MANDIR = man
+# command used to get root (needed for tarball creation)
GETROOT = fakeroot
-# Enable text colors
-CONFIG_COLOR_TEXT = y
-# Enable colormap setup
-CONFIG_SET_COLORMAP = y
-# Enable splash screen
-CONFIG_SPLASH_SCREEN = n
-# Enable md5 passwords
-USE_MD5_PASSWORDS = y
-
# We use fixed addresses to avoid overlap when relocating
# and other trouble with initrd
#
CROSS =
-# The flags for the target compiler.
+# The flags for the yaboot binary.
#
-CFLAGS = -Os -nostdinc -Wall -isystem `gcc -print-file-name=include` -fsigned-char
-CFLAGS += -DVERSION=\"${VERSION}\" #"
-CFLAGS += -DTEXTADDR=$(TEXTADDR) -DDEBUG=$(DEBUG)
-CFLAGS += -DMALLOCADDR=$(MALLOCADDR) -DMALLOCSIZE=$(MALLOCSIZE)
-CFLAGS += -DKERNELADDR=$(KERNELADDR)
-CFLAGS += -I ./include
+YBCFLAGS = -Os $(CFLAGS) -nostdinc -Wall -isystem `gcc -print-file-name=include` -fsigned-char
+YBCFLAGS += -DVERSION=\"${VERSION}\" #"
+YBCFLAGS += -DTEXTADDR=$(TEXTADDR) -DDEBUG=$(DEBUG)
+YBCFLAGS += -DMALLOCADDR=$(MALLOCADDR) -DMALLOCSIZE=$(MALLOCSIZE)
+YBCFLAGS += -DKERNELADDR=$(KERNELADDR)
+YBCFLAGS += -I ./include
ifeq ($(CONFIG_COLOR_TEXT),y)
-CFLAGS += -DCONFIG_COLOR_TEXT
+YBCFLAGS += -DCONFIG_COLOR_TEXT
endif
ifeq ($(CONFIG_SET_COLORMAP),y)
-CFLAGS += -DCONFIG_SET_COLORMAP
+YBCFLAGS += -DCONFIG_SET_COLORMAP
endif
-ifeq ($(CONFIG_SPLASH_SCREEN),y)
-CFLAGS += -DCONFIG_SPLASH_SCREEN
+ifeq ($(USE_MD5_PASSWORDS),y)
+YBCFLAGS += -DUSE_MD5_PASSWORDS
endif
-ifeq ($(USE_MD5_PASSWORDS),y)
-CFLAGS += -DUSE_MD5_PASSWORDS
+ifeq ($(CONFIG_FS_XFS),y)
+YBCFLAGS += -DCONFIG_FS_XFS
+endif
+
+ifeq ($(CONFIG_FS_REISERFS),y)
+YBCFLAGS += -DCONFIG_FS_REISERFS
endif
# Link flags
# Libraries
#
LLIBS = lib/libext2fs.a
-#LLIBS = -l ext2fs
+
+# For compiling userland utils
+#
+UCFLAGS = -Os $(CFLAGS) -Wall -I/usr/include
# For compiling build-tools that run on the host.
#
HOSTCC = gcc
-HOSTCFLAGS = -I/usr/include $(CFLAGS)
+HOSTCFLAGS = -O2 $(CFLAGS) -Wall -I/usr/include
## End of configuration section
OBJS = second/crt0.o second/yaboot.o second/cache.o second/prom.o second/file.o \
second/partition.o second/fs.o second/cfg.o second/setjmp.o second/cmdline.o \
- second/fs_of.o second/fs_ext2.o second/fs_reiserfs.o second/fs_iso.o second/iso_util.o \
+ second/fs_of.o second/fs_ext2.o second/fs_iso.o second/iso_util.o \
lib/nosys.o lib/string.o lib/strtol.o lib/vsprintf.o lib/ctype.o lib/malloc.o lib/strstr.o
-ifeq ($(CONFIG_SPLASH_SCREEN),y)
-OBJS += second/gui/effects.o second/gui/colormap.o second/gui/video.o second/gui/pcx.o
-endif
-
ifeq ($(USE_MD5_PASSWORDS),y)
OBJS += second/md5.o
endif
+ifeq ($(CONFIG_FS_XFS),y)
+OBJS += second/fs_xfs.o
+endif
+
+ifeq ($(CONFIG_FS_REISERFS),y)
+OBJS += second/fs_reiserfs.o
+endif
+
CC = $(CROSS)gcc
LD = $(CROSS)ld
AS = $(CROSS)as
OBJCOPY = $(CROSS)objcopy
-all: yaboot addnote mkofboot
-
lgcc = `$(CC) -print-libgcc-file-name`
+all: yaboot addnote mkofboot
+
yaboot: $(OBJS)
$(LD) $(LFLAGS) $(OBJS) $(LLIBS) $(lgcc) -o second/$@
chmod -x second/yaboot
addnote:
- $(HOSTCC) $(HOSTCFLAGS) -o util/addnote util/addnote.c
+ $(CC) $(UCFLAGS) -o util/addnote util/addnote.c
elfextract:
$(HOSTCC) $(HOSTCFLAGS) -o util/elfextract util/elfextract.c
ln -sf ybin ybin/mkofboot
%.o: %.c
- $(CC) $(CFLAGS) -c -o $@ $<
+ $(CC) $(YBCFLAGS) -c -o $@ $<
%.o: %.S
- $(CC) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $<
+ $(CC) $(YBCFLAGS) -D__ASSEMBLY__ -c -o $@ $<
dep:
makedepend -Iinclude *.c lib/*.c util/*.c gui/*.c
* Daniel Jacobowitz <dan@debian.org> for Debian packaging, advice and busybox help.
* Benjamin Herrenschmidt <benh@kernel.crashing.org> for yaboot and great work on the kernel.
+ * Colin Walters <walters@verbum.org> for advice, help with XFS and general code auditing.
* Charles Stevenson <csteven@newhope.terraplex.com> for adding color config support to yaboot.
* Chris Emerson <cemerson@chiark.greenend.org.uk> for the Forth code in ofboot.
* iNOUE Koich! <inoue@ma.ns.musashi-tech.ac.jp> for advice and help [re]writing ofboot's Forth code.
+2001-10-09 Ethan Benson <erbenson@alaska.net>
+
+ * Version 1.3.4-pre1
+
+ * yaboot:
+ - Add SGI XFS filesystem support.
+ - Rewrite OpenFirmware device path parsing code. This fixes
+ many bugs and inconsistencies in yaboot's file loading.
+ - Fix OpenFirmware filesystem support to automatically convert
+ path separator from / to \. CDROM authors no longer need to use
+ hacks like image=\\install\\powermac\\vmlinux.
+ - Fix kernel loading on some systems.
+ - Allow for getting files from tftp server that does not run a
+ bootpd/dhcpd.
+ - Fix a great deal of incorrect format strings which could cause
+ yaboot crashes.
+ - Fix all filesystems to properly return error conditions, and
+ report those error conditions (instead of just saying `image not
+ found').
+ - Add `help' command to yaboot which prints out basic usage information.
+ - General cruft removal and code cleanup.
+
+ * Makefile cleanup, make filesystems configurable.
+
2001-09-25 Ethan Benson <erbenson@alaska.net>
* Version 1.3.3
--- /dev/null
+/*
+ * errors.h - Definitions of error numbers returned by filesystems
+ *
+ * Copyright (C) 2001 Ethan Benson
+ *
+ * Copyright (C) 1999 Benjamin Herrenschmidt
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Simple error codes */
+#define FILE_ERR_OK 0
+#define FILE_ERR_EOF -1
+#define FILE_ERR_NOTFOUND -2
+#define FILE_CANT_SEEK -3
+#define FILE_IOERR -4
+#define FILE_BAD_PATH -5
+#define FILE_ERR_BAD_TYPE -6
+#define FILE_ERR_NOTDIR -7
+#define FILE_ERR_BAD_FSYS -8
+#define FILE_ERR_SYMLINK_LOOP -9
+#define FILE_ERR_LENGTH -10
+#define FILE_ERR_FSBUSY -11
+#define FILE_ERR_BADDEV -12
#define FILE_MAX_PATH 1024
-/* Simple error codes */
-#define FILE_ERR_OK 0
-#define FILE_ERR_EOF -1
-#define FILE_ERR_NOTFOUND -2
-#define FILE_CANT_SEEK -3
-#define FILE_IOERR -4
-#define FILE_BAD_PATH -5
-#define FILE_ERR_BAD_TYPE -6
-#define FILE_ERR_BAD_FSYS -7
-#define FILE_ERR_SYMLINK_LOOP -8
-#define FILE_ERR_LENGTH -9
-
/* Device kind */
#define FILE_DEVICE_BLOCK 1
#define FILE_DEVICE_NET 2
// unsigned int part_count;
};
-extern int open_file( const struct boot_fspec_t* spec,
- struct boot_file_t* file);
+extern int
+open_file(const struct boot_fspec_t* spec,
+ struct boot_file_t* file);
+
+extern int
+parse_device_path(char *imagepath, char *defdevice, int defpart,
+ char *deffile, struct boot_fspec_t *result);
+#if 0
extern int validate_fspec(
struct boot_fspec_t* spec,
char* default_device,
char* of_device,
char** file_spec,
int* partition);
-
+#endif
#endif
#include "partition.h"
#include "file.h"
+int fserrorno;
+
struct fs_t {
const char* name;
extern const struct fs_t *fs_of;
extern const struct fs_t *fs_of_netboot;
-const struct fs_t *fs_open( struct boot_file_t *file, const char *dev_name,
- struct partition_t *part, const char *file_name );
+const struct fs_t *fs_open(struct boot_file_t *file, const char *dev_name,
+ struct partition_t *part, const char *file_name);
#if DEBUG
-# define DEBUG_ENTER prom_printf( "--> %s\n", __PRETTY_FUNCTION__ );
+# define DEBUG_ENTER prom_printf( "--> %s\n", __PRETTY_FUNCTION__ )
# define DEBUG_LEAVE(str) \
- prom_printf( "<-- %s - %s\n", __PRETTY_FUNCTION__, #str );
+ prom_printf( "<-- %s - %s\n", __PRETTY_FUNCTION__, #str )
+# define DEBUG_LEAVE_F(args...)\
+{\
+ prom_printf( "<-- %s - %d\n", __PRETTY_FUNCTION__, ## args );\
+}
# define DEBUG_F(fmt, args...)\
{\
prom_printf( " %s - ", __PRETTY_FUNCTION__ );\
prom_printf( fmt, ## args );\
}
-# define DEBUG_OPEN DEBUG_F( "dev=%s, part=0x%08lx (%d), file_name=%s\n",\
+# define DEBUG_OPEN DEBUG_F( "dev=%s, part=0x%p (%d), file_name=%s\n",\
dev_name, part, part ? part->part_number : -1,\
- file_name);
+ file_name)
+# define DEBUG_SLEEP prom_sleep(3)
#else
#define DEBUG_ENTER
#define DEBUG_LEAVE(x)
+#define DEBUG_LEAVE_F(args...)
#define DEBUG_F(fmt, args...)
#define DEBUG_OPEN
+#define DEBUG_SLEEP
#endif
#endif
+++ /dev/null
-extern void fxDisplaySplash(struct boot_fspec_t *filespec);
-int fxReadImage(struct boot_file_t *file, unsigned int filesize, void *base);
-
void prom_putchar (char);
int prom_nbgetchar();
+#ifdef __GNUC__
+void prom_vprintf (char *fmt, va_list ap) __attribute__ ((format (printf, 1, 0)));
+void prom_fprintf (prom_handle dev, char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+void prom_printf (char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+#else
void prom_vprintf (char *fmt, va_list ap);
void prom_fprintf (prom_handle dev, char *fmt, ...);
void prom_printf (char *fmt, ...);
+#endif
+
+void prom_perror (int error, char *filename);
void prom_readline (char *prompt, char *line, int len);
int prom_set_color(prom_handle device, int color, int r, int g, int b);
void prom_exit ();
void prom_abort (char *fmt, ...);
+void prom_sleep (int seconds);
int prom_interpret (char *forth);
extern int strcmp(const char *,const char *);
extern int strncmp(const char *,const char *,size_t);
extern int strnicmp(const char *, const char *, size_t);
-extern void *strdup(char *str);
+extern char *strdup(char const *str);
extern void * memset(void *,int,size_t);
extern void * memcpy(void *,const void *,size_t);
+++ /dev/null
-#ifndef __VIDEO_H__
-#define __VIDEO_H__
-
-
-
-#endif
\ No newline at end of file
--- /dev/null
+/*
+ * xfs.h - an extraction from xfsprogs-1.3.5/include/xfs* into one file
+ *
+ * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#ifndef _BITS_TYPES_H
+typedef signed char __int8_t;
+typedef unsigned char __uint8_t;
+typedef short __int16_t;
+typedef unsigned short __uint16_t;
+typedef int __int32_t;
+typedef unsigned int __uint32_t;
+typedef long long __int64_t;
+typedef unsigned long long __uint64_t;
+#endif
+
+typedef __uint64_t xfs_ino_t;
+typedef __uint32_t xfs_agino_t;
+typedef __int64_t xfs_daddr_t;
+typedef __int64_t xfs_off_t;
+typedef __uint8_t uuid_t[16];
+
+
+/* those are from xfs_types.h */
+
+typedef __uint32_t xfs_agblock_t; /* blockno in alloc. group */
+typedef __uint32_t xfs_extlen_t; /* extent length in blocks */
+typedef __uint32_t xfs_agnumber_t; /* allocation group number */
+typedef __int32_t xfs_extnum_t; /* # of extents in a file */
+typedef __int16_t xfs_aextnum_t; /* # extents in an attribute fork */
+typedef __int64_t xfs_fsize_t; /* bytes in a file */
+
+typedef __uint32_t xfs_dablk_t; /* dir/attr block number (in file) */
+typedef __uint32_t xfs_dahash_t; /* dir/attr hash value */
+
+/*
+ * Disk based types:
+ */
+typedef __uint64_t xfs_dfsbno_t; /* blockno in filesystem (agno|agbno) */
+typedef __uint64_t xfs_drfsbno_t; /* blockno in filesystem (raw) */
+typedef __uint64_t xfs_drtbno_t; /* extent (block) in realtime area */
+typedef __uint64_t xfs_dfiloff_t; /* block number in a file */
+
+typedef __uint64_t xfs_fsblock_t; /* blockno in filesystem (agno|agbno) */
+typedef __uint64_t xfs_fileoff_t; /* block number in a file */
+typedef __uint64_t xfs_filblks_t; /* number of blocks in a file */
+
+
+/* those are from xfs_sb.h */
+
+#define XFS_SB_MAGIC 0x58465342 /* 'XFSB'*/
+#define XFS_SB_VERSION_4 4 /* 6.2+ - bitmask version */
+#define XFS_SB_VERSION_NUMBITS 0x000f
+
+typedef struct xfs_sb
+{
+ __uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */
+ __uint32_t sb_blocksize; /* logical block size, bytes */
+ xfs_drfsbno_t sb_dblocks; /* number of data blocks */
+ xfs_drfsbno_t sb_rblocks; /* number of realtime blocks */
+ xfs_drtbno_t sb_rextents; /* number of realtime extents */
+ uuid_t sb_uuid; /* file system unique id */
+ xfs_dfsbno_t sb_logstart; /* starting block of log if internal */
+ xfs_ino_t sb_rootino; /* root inode number */
+ xfs_ino_t sb_rbmino; /* bitmap inode for realtime extents */
+ xfs_ino_t sb_rsumino; /* summary inode for rt bitmap */
+ xfs_agblock_t sb_rextsize; /* realtime extent size, blocks */
+ xfs_agblock_t sb_agblocks; /* size of an allocation group */
+ xfs_agnumber_t sb_agcount; /* number of allocation groups */
+ xfs_extlen_t sb_rbmblocks; /* number of rt bitmap blocks */
+ xfs_extlen_t sb_logblocks; /* number of log blocks */
+ __uint16_t sb_versionnum; /* header version == XFS_SB_VERSION */
+ __uint16_t sb_sectsize; /* volume sector size, bytes */
+ __uint16_t sb_inodesize; /* inode size, bytes */
+ __uint16_t sb_inopblock; /* inodes per block */
+ char sb_fname[12]; /* file system name */
+ __uint8_t sb_blocklog; /* log2 of sb_blocksize */
+ __uint8_t sb_sectlog; /* log2 of sb_sectsize */
+ __uint8_t sb_inodelog; /* log2 of sb_inodesize */
+ __uint8_t sb_inopblog; /* log2 of sb_inopblock */
+ __uint8_t sb_agblklog; /* log2 of sb_agblocks (rounded up) */
+ __uint8_t sb_rextslog; /* log2 of sb_rextents */
+ __uint8_t sb_inprogress; /* mkfs is in progress, don't mount */
+ __uint8_t sb_imax_pct; /* max % of fs for inode space */
+ /* statistics */
+ /*
+ * These fields must remain contiguous. If you really
+ * want to change their layout, make sure you fix the
+ * code in xfs_trans_apply_sb_deltas().
+ */
+ __uint64_t sb_icount; /* allocated inodes */
+ __uint64_t sb_ifree; /* free inodes */
+ __uint64_t sb_fdblocks; /* free data blocks */
+ __uint64_t sb_frextents; /* free realtime extents */
+ /*
+ * End contiguous fields.
+ */
+ xfs_ino_t sb_uquotino; /* user quota inode */
+ xfs_ino_t sb_gquotino; /* group quota inode */
+ __uint16_t sb_qflags; /* quota flags */
+ __uint8_t sb_flags; /* misc. flags */
+ __uint8_t sb_shared_vn; /* shared version number */
+ xfs_extlen_t sb_inoalignmt; /* inode chunk alignment, fsblocks */
+ __uint32_t sb_unit; /* stripe or raid unit */
+ __uint32_t sb_width; /* stripe or raid width */
+ __uint8_t sb_dirblklog; /* log2 of dir block size (fsbs) */
+ __uint8_t sb_dummy[7]; /* padding */
+} xfs_sb_t;
+
+
+/* those are from xfs_btree.h */
+
+/*
+ * Long form header: bmap btrees.
+ */
+typedef struct xfs_btree_lblock
+{
+ __uint32_t bb_magic; /* magic number for block type */
+ __uint16_t bb_level; /* 0 is a leaf */
+ __uint16_t bb_numrecs; /* current # of data records */
+ xfs_dfsbno_t bb_leftsib; /* left sibling block or NULLDFSBNO */
+ xfs_dfsbno_t bb_rightsib; /* right sibling block or NULLDFSBNO */
+} xfs_btree_lblock_t;
+
+/*
+ * Combined header and structure, used by common code.
+ */
+typedef struct xfs_btree_hdr
+{
+ __uint32_t bb_magic; /* magic number for block type */
+ __uint16_t bb_level; /* 0 is a leaf */
+ __uint16_t bb_numrecs; /* current # of data records */
+} xfs_btree_hdr_t;
+
+typedef struct xfs_btree_block
+{
+ xfs_btree_hdr_t bb_h; /* header */
+ union {
+ struct {
+ xfs_agblock_t bb_leftsib;
+ xfs_agblock_t bb_rightsib;
+ } s; /* short form pointers */
+ struct {
+ xfs_dfsbno_t bb_leftsib;
+ xfs_dfsbno_t bb_rightsib;
+ } l; /* long form pointers */
+ } bb_u; /* rest */
+} xfs_btree_block_t;
+
+/* those are from xfs_bmap_btree.h */
+
+/*
+ * Bmap root header, on-disk form only.
+ */
+typedef struct xfs_bmdr_block
+{
+ __uint16_t bb_level; /* 0 is a leaf */
+ __uint16_t bb_numrecs; /* current # of data records */
+} xfs_bmdr_block_t;
+
+/*
+ * Bmap btree record and extent descriptor.
+ * For 32-bit kernels,
+ * l0:31 is an extent flag (value 1 indicates non-normal).
+ * l0:0-30 and l1:9-31 are startoff.
+ * l1:0-8, l2:0-31, and l3:21-31 are startblock.
+ * l3:0-20 are blockcount.
+ * For 64-bit kernels,
+ * l0:63 is an extent flag (value 1 indicates non-normal).
+ * l0:9-62 are startoff.
+ * l0:0-8 and l1:21-63 are startblock.
+ * l1:0-20 are blockcount.
+ */
+
+#define BMBT_USE_64 1
+
+typedef struct xfs_bmbt_rec_32
+{
+ __uint32_t l0, l1, l2, l3;
+} xfs_bmbt_rec_32_t;
+typedef struct xfs_bmbt_rec_64
+{
+ __uint64_t l0, l1;
+} xfs_bmbt_rec_64_t;
+
+#if BMBT_USE_64
+typedef __uint64_t xfs_bmbt_rec_base_t; /* use this for casts */
+typedef xfs_bmbt_rec_64_t xfs_bmbt_rec_t, xfs_bmdr_rec_t;
+#else /* !BMBT_USE_64 */
+typedef __uint32_t xfs_bmbt_rec_base_t; /* use this for casts */
+typedef xfs_bmbt_rec_32_t xfs_bmbt_rec_t, xfs_bmdr_rec_t;
+#endif /* BMBT_USE_64 */
+
+/*
+ * Key structure for non-leaf levels of the tree.
+ */
+typedef struct xfs_bmbt_key
+{
+ xfs_dfiloff_t br_startoff; /* starting file offset */
+} xfs_bmbt_key_t, xfs_bmdr_key_t;
+
+typedef xfs_dfsbno_t xfs_bmbt_ptr_t, xfs_bmdr_ptr_t; /* btree pointer type */
+ /* btree block header type */
+typedef struct xfs_btree_lblock xfs_bmbt_block_t;
+
+
+/* those are from xfs_dir2.h */
+/*
+ * Directory version 2.
+ * There are 4 possible formats:
+ * shortform
+ * single block - data with embedded leaf at the end
+ * multiple data blocks, single leaf+freeindex block
+ * data blocks, node&leaf blocks (btree), freeindex blocks
+ *
+ * The shortform format is in xfs_dir2_sf.h.
+ * The single block format is in xfs_dir2_block.h.
+ * The data block format is in xfs_dir2_data.h.
+ * The leaf and freeindex block formats are in xfs_dir2_leaf.h.
+ * Node blocks are the same as the other version, in xfs_da_btree.h.
+ */
+
+/*
+ * Byte offset in data block and shortform entry.
+ */
+typedef __uint16_t xfs_dir2_data_off_t;
+
+/*
+ * Byte offset in a directory.
+ */
+typedef xfs_off_t xfs_dir2_off_t;
+
+/* those are from xfs_da_btree.h */
+/*========================================================================
+ * Directory Structure when greater than XFS_LBSIZE(mp) bytes.
+ *========================================================================*/
+
+/*
+ * This structure is common to both leaf nodes and non-leaf nodes in the Btree.
+ *
+ * Is is used to manage a doubly linked list of all blocks at the same
+ * level in the Btree, and to identify which type of block this is.
+ */
+#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */
+#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */
+
+typedef struct xfs_da_blkinfo {
+ xfs_dablk_t forw; /* previous block in list */
+ xfs_dablk_t back; /* following block in list */
+ __uint16_t magic; /* validity check on block */
+ __uint16_t pad; /* unused */
+} xfs_da_blkinfo_t;
+
+/*
+ * This is the structure of the root and intermediate nodes in the Btree.
+ * The leaf nodes are defined above.
+ *
+ * Entries are not packed.
+ *
+ * Since we have duplicate keys, use a binary search but always follow
+ * all match in the block, not just the first match found.
+ */
+
+typedef struct xfs_da_intnode {
+ struct xfs_da_node_hdr { /* constant-structure header block */
+ xfs_da_blkinfo_t info; /* block type, links, etc. */
+ __uint16_t count; /* count of active entries */
+ __uint16_t level; /* level above leaves (leaf == 0) */
+ } hdr;
+ struct xfs_da_node_entry {
+ xfs_dahash_t hashval; /* hash value for this descendant */
+ xfs_dablk_t before; /* Btree block before this key */
+ } btree[1]; /* variable sized array of keys */
+} xfs_da_intnode_t;
+
+
+/* those are from xfs_dir2_data.h */
+/*
+ * Directory format 2, data block structures.
+ */
+
+/*
+ * Constants.
+ */
+#define XFS_DIR2_DATA_FREE_TAG 0xffff
+#define XFS_DIR2_DATA_FD_COUNT 3
+
+/*
+ * Structures.
+ */
+
+/*
+ * Describe a free area in the data block.
+ * The freespace will be formatted as a xfs_dir2_data_unused_t.
+ */
+typedef struct xfs_dir2_data_free {
+ xfs_dir2_data_off_t offset; /* start of freespace */
+ xfs_dir2_data_off_t length; /* length of freespace */
+} xfs_dir2_data_free_t;
+
+/*
+ * Header for the data blocks.
+ * Always at the beginning of a directory-sized block.
+ * The code knows that XFS_DIR2_DATA_FD_COUNT is 3.
+ */
+typedef struct xfs_dir2_data_hdr {
+ __uint32_t magic; /* XFS_DIR2_DATA_MAGIC */
+ /* or XFS_DIR2_BLOCK_MAGIC */
+ xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT];
+} xfs_dir2_data_hdr_t;
+
+/*
+ * Active entry in a data block. Aligned to 8 bytes.
+ * Tag appears as the last 2 bytes.
+ */
+typedef struct xfs_dir2_data_entry {
+ xfs_ino_t inumber; /* inode number */
+ __uint8_t namelen; /* name length */
+ __uint8_t name[1]; /* name bytes, no null */
+ /* variable offset */
+ xfs_dir2_data_off_t tag; /* starting offset of us */
+} xfs_dir2_data_entry_t;
+
+/*
+ * Unused entry in a data block. Aligned to 8 bytes.
+ * Tag appears as the last 2 bytes.
+ */
+typedef struct xfs_dir2_data_unused {
+ __uint16_t freetag; /* XFS_DIR2_DATA_FREE_TAG */
+ xfs_dir2_data_off_t length; /* total free length */
+ /* variable offset */
+ xfs_dir2_data_off_t tag; /* starting offset of us */
+} xfs_dir2_data_unused_t;
+
+typedef union {
+ xfs_dir2_data_entry_t entry;
+ xfs_dir2_data_unused_t unused;
+} xfs_dir2_data_union_t;
+
+
+/* those are from xfs_dir2_leaf.h */
+/*
+ * Directory version 2, leaf block structures.
+ */
+
+/*
+ * Leaf block header.
+ */
+typedef struct xfs_dir2_leaf_hdr {
+ xfs_da_blkinfo_t info; /* header for da routines */
+ __uint16_t count; /* count of entries */
+ __uint16_t stale; /* count of stale entries */
+} xfs_dir2_leaf_hdr_t;
+
+
+/* those are from xfs_dir2_block.h */
+/*
+ * xfs_dir2_block.h
+ * Directory version 2, single block format structures
+ */
+
+/*
+ * The single block format is as follows:
+ * xfs_dir2_data_hdr_t structure
+ * xfs_dir2_data_entry_t and xfs_dir2_data_unused_t structures
+ * xfs_dir2_leaf_entry_t structures
+ * xfs_dir2_block_tail_t structure
+ */
+
+#define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: for one block dirs */
+
+typedef struct xfs_dir2_block_tail {
+ __uint32_t count; /* count of leaf entries */
+ __uint32_t stale; /* count of stale lf entries */
+} xfs_dir2_block_tail_t;
+
+
+/* those are from xfs_dir2_sf.h */
+
+/*
+ * Directory layout when stored internal to an inode.
+ *
+ * Small directories are packed as tightly as possible so as to
+ * fit into the literal area of the inode.
+ */
+
+/*
+ * Inode number stored as 8 8-bit values.
+ */
+typedef struct { __uint8_t i[8]; } xfs_dir2_ino8_t;
+
+/*
+ * Inode number stored as 4 8-bit values.
+ * Works a lot of the time, when all the inode numbers in a directory
+ * fit in 32 bits.
+ */
+typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t;
+
+typedef union {
+ xfs_dir2_ino8_t i8;
+ xfs_dir2_ino4_t i4;
+} xfs_dir2_inou_t;
+
+/*
+ * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t.
+ * Only need 16 bits, this is the byte offset into the single block form.
+ */
+typedef struct { __uint8_t i[2]; } xfs_dir2_sf_off_t;
+
+/*
+ * The parent directory has a dedicated field, and the self-pointer must
+ * be calculated on the fly.
+ *
+ * Entries are packed toward the top as tightly as possible. The header
+ * and the elements must be bcopy()'d out into a work area to get correct
+ * alignment for the inode number fields.
+ */
+typedef struct xfs_dir2_sf_hdr {
+ __uint8_t count; /* count of entries */
+ __uint8_t i8count; /* count of 8-byte inode #s */
+ xfs_dir2_inou_t parent; /* parent dir inode number */
+} xfs_dir2_sf_hdr_t;
+
+typedef struct xfs_dir2_sf_entry {
+ __uint8_t namelen; /* actual name length */
+ xfs_dir2_sf_off_t offset; /* saved offset */
+ __uint8_t name[1]; /* name, variable size */
+ xfs_dir2_inou_t inumber; /* inode number, var. offset */
+} xfs_dir2_sf_entry_t;
+
+typedef struct xfs_dir2_sf {
+ xfs_dir2_sf_hdr_t hdr; /* shortform header */
+ xfs_dir2_sf_entry_t list[1]; /* shortform entries */
+} xfs_dir2_sf_t;
+
+/* those are from xfs_dinode.h */
+
+#define XFS_DINODE_VERSION_1 1
+#define XFS_DINODE_VERSION_2 2
+#define XFS_DINODE_MAGIC 0x494e /* 'IN' */
+
+/*
+ * Disk inode structure.
+ * This is just the header; the inode is expanded to fill a variable size
+ * with the last field expanding. It is split into the core and "other"
+ * because we only need the core part in the in-core inode.
+ */
+typedef struct xfs_timestamp {
+ __int32_t t_sec; /* timestamp seconds */
+ __int32_t t_nsec; /* timestamp nanoseconds */
+} xfs_timestamp_t;
+
+/*
+ * Note: Coordinate changes to this structure with the XFS_DI_* #defines
+ * below and the offsets table in xfs_ialloc_log_di().
+ */
+typedef struct xfs_dinode_core
+{
+ __uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */
+ __uint16_t di_mode; /* mode and type of file */
+ __int8_t di_version; /* inode version */
+ __int8_t di_format; /* format of di_c data */
+ __uint16_t di_onlink; /* old number of links to file */
+ __uint32_t di_uid; /* owner's user id */
+ __uint32_t di_gid; /* owner's group id */
+ __uint32_t di_nlink; /* number of links to file */
+ __uint16_t di_projid; /* owner's project id */
+ __uint8_t di_pad[10]; /* unused, zeroed space */
+ xfs_timestamp_t di_atime; /* time last accessed */
+ xfs_timestamp_t di_mtime; /* time last modified */
+ xfs_timestamp_t di_ctime; /* time created/inode modified */
+ xfs_fsize_t di_size; /* number of bytes in file */
+ xfs_drfsbno_t di_nblocks; /* # of direct & btree blocks used */
+ xfs_extlen_t di_extsize; /* basic/minimum extent size for file */
+ xfs_extnum_t di_nextents; /* number of extents in data fork */
+ xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/
+ __uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */
+ __int8_t di_aformat; /* format of attr fork's data */
+ __uint32_t di_dmevmask; /* DMIG event mask */
+ __uint16_t di_dmstate; /* DMIG state info */
+ __uint16_t di_flags; /* random flags, XFS_DIFLAG_... */
+ __uint32_t di_gen; /* generation number */
+} xfs_dinode_core_t;
+
+typedef struct xfs_dinode
+{
+ xfs_dinode_core_t di_core;
+ xfs_agino_t di_next_unlinked;/* agi unlinked list ptr */
+ union {
+ xfs_bmdr_block_t di_bmbt; /* btree root block */
+ xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */
+ xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */
+ char di_c[1]; /* local contents */
+ } di_u;
+} xfs_dinode_t;
+
+/*
+ * Values for di_format
+ */
+typedef enum xfs_dinode_fmt
+{
+ XFS_DINODE_FMT_DEV, /* CHR, BLK: di_dev */
+ XFS_DINODE_FMT_LOCAL, /* DIR, REG: di_c */
+ /* LNK: di_symlink */
+ XFS_DINODE_FMT_EXTENTS, /* DIR, REG, LNK: di_bmx */
+ XFS_DINODE_FMT_BTREE, /* DIR, REG, LNK: di_bmbt */
+ XFS_DINODE_FMT_UUID /* MNT: di_uuid */
+} xfs_dinode_fmt_t;
+
+/*
+ * File types (mode field)
+ */
+#define IFMT 0170000 /* type of file */
+#define IFDIR 0040000 /* directory */
+#define IFREG 0100000 /* regular */
+#define IFLNK 0120000 /* symbolic link */
struct boot_fspec_t kernel;
struct boot_fspec_t rd;
struct boot_fspec_t sysmap;
- struct boot_fspec_t splash;
char* args;
};
extern char *bootpath;
extern int bootpartition;
-#endif
\ No newline at end of file
+#endif
malloc_ptr = (char *) ptr;
}
-void *strdup(char *str)
+char *strdup(char const *str)
{
char *p = malloc(strlen(str) + 1);
-
- strcpy(p, str);
+ if (p)
+ strcpy(p, str);
return p;
}
{cft_strg, "pause-message", NULL},
{cft_strg, "init-code", NULL},
{cft_strg, "init-message", NULL},
- {cft_strg, "splash", NULL},
{cft_strg, "fgcolor", NULL},
{cft_strg, "bgcolor", NULL},
{cft_end, NULL, NULL}};
{cft_flag, "pause-after", NULL},
{cft_strg, "pause-message", NULL},
{cft_flag, "novideo", NULL},
- {cft_strg, "splash", NULL},
{cft_strg, "sysmap", NULL},
{cft_end, NULL, NULL}};
if (alias)
printlabel (alias, 0);
}
- prom_printf ("\n\nYou can also type in custom image locations, in the form\n"
- "{prom_path;}partno/path_to_image or {prom_path;}{partno}[start-end]\n"
- "Example: hd:3,/vmlinux\n\n");
+ prom_printf("\n");
}
char *cfg_get_default (void)
#include "string.h"
#include "partition.h"
#include "fs.h"
+#include "errors.h"
extern char bootdevice[1024];
the string passed in parameters is changed since 0 are put in place
of some separators to terminate the various strings
*/
+
+int
+parse_device_path(char *imagepath, char *defdevice, int defpart,
+ char *deffile, struct boot_fspec_t *result)
+{
+ char *ptr;
+ char *ipath = strdup(imagepath);
+ char *defdev = strdup(defdevice);
+
+ result->dev = NULL;
+ result->part = -1;
+ result->file = NULL;
+
+ if (!strstr(defdev, "ethernet") && !strstr(defdev, "enet")) {
+ if ((ptr = strchr(defdev, ':')) != NULL)
+ *ptr = 0; /* remove trailing : from defdevice if necessary */
+ }
+
+ if (!imagepath)
+ goto punt;
+
+ if ((ptr = strrchr(ipath, ',')) != NULL) {
+ result->file = strdup(ptr+1);
+ /* Trim the filename off */
+ *ptr = 0;
+ }
+
+ if (strstr(ipath, "ethernet") || strstr(ipath, "enet"))
+ result->dev = strdup(ipath);
+ else if ((ptr = strchr(ipath, ':')) != NULL) {
+ *ptr = 0;
+ result->dev = strdup(ipath);
+ if (*(ptr+1))
+ result->part = simple_strtol(ptr+1, NULL, 10);
+ } else if (strlen(ipath)) {
+ result->file = strdup(ipath);
+ } else {
+ return 0;
+ }
+
+ punt:
+ if (!result->dev)
+ result->dev = strdup(defdev);
+
+ if (result->part < 0)
+ result->part = defpart;
+
+ if (!result->file)
+ result->file = strdup(deffile);
+ free(ipath);
+ return 1;
+}
+
+#if 0
char *
parse_device_path(char *of_device, char **file_spec, int *partition)
{
if (partition)
*partition = -1;
+ DEBUG_F("of_device before parsing: %s\n", of_device);
p = strchr(of_device, ':');
- if (p)
- *p = 0;
- else
- return of_device;
-
- last = ++p;
+ DEBUG_F("of_device after parsing: %s\n", p);
+
+ if (!p) { /* if null terminated we are finished */
+ DEBUG_F("of_device: %s\n", of_device);
+ return of_device;
+ }
+#if 0 /* this is broken crap, breaks netboot entirely */
+ else if (strstr(of_device, "ethernet") != NULL)
+ p = strchr(of_device, ','); /* skip over ip all the way to the ',' */
+ else if (strstr(of_device, "enet") != NULL)
+ p = strchr(of_device, ','); /* skip over ip all the way to the ',' */
+#endif
+ *p = 0;
+ last = ++p; /* sets to start of second part */
while(*p && *p != ',') {
if (!isdigit (*p)) {
- p = last;
- break;
- }
- ++p;
+ p = last;
+ break;
+ }
+ ++p;
}
if (p != last) {
- *(p++) = 0;
- if (partition)
- *partition = simple_strtol(last, NULL, 10);
+ *(p++) = 0;
+ if (partition)
+ *partition = simple_strtol(last, NULL, 10);
}
if (*p && file_spec)
- *file_spec = p;
-
- return of_device;
+ *file_spec = p;
+ DEBUG_F("of_device: %s\n", of_device);
+ strcat(of_device, ":");
+ DEBUG_F("of_device after strcat: %s\n", of_device);
+ return of_device;
}
int
return FILE_ERR_OK;
}
+#endif
+
static int
file_block_open( struct boot_file_t* file,
const char* dev_name,
prom_printf("no partitions found.\n");
#endif
for (p = parts; p && !found; p=p->next) {
-#if DEBUG
- prom_printf("number: %02d, start: 0x%08lx, length: 0x%08lx\n",
+ DEBUG_F("number: %02d, start: 0x%08lx, length: 0x%08lx\n",
p->part_number, p->part_start, p->part_size );
-#endif
if (partition == -1) {
file->fs = fs_open( file, dev_name, p, file_name );
if (file->fs != NULL)
/* Note: we don't skip when found is NULL since we can, in some
* cases, let OF figure out a default partition.
*/
- DEBUG_F( "Using OF defaults.. (found = 0x%x)\n", found );
+ DEBUG_F( "Using OF defaults.. (found = %p)\n", found );
file->fs = fs_open( file, dev_name, found, file_name );
bail:
if (parts)
partitions_free(parts);
- return file->fs ? FILE_ERR_OK : FILE_ERR_NOTFOUND;
+ return fserrorno;
}
static int
int open_file( const struct boot_fspec_t* spec,
struct boot_file_t* file)
{
- static char temp[1024];
+// static char temp[1024];
static char temps[64];
- char *dev_name;
- char *file_name = NULL;
+// char *dev_name;
+// char *file_name = NULL;
phandle dev;
int result;
int partition;
/* First, see if a device was specified for the kernel
* if not, we hope that the user wants a kernel on the same
* drive and partition as yaboot itself */
+#if 0 /* this is crap */
if (!spec->dev)
strcpy(spec->dev, bootdevice);
strncpy(temp,spec->dev,1024);
if (file_name == NULL)
file_name = (char *)spec->file;
if (file_name == NULL) {
- prom_printf("booting without a file name not yet supported !\n");
- return FILE_ERR_NOTFOUND;
+ prom_printf("Configuration error: null filename\n");
+ return FILE_ERR_NOTFOUND;
}
if (partition == -1)
+#endif
partition = spec->part;
-#if DEBUG
- prom_printf("dev_path = %s\nfile_name = %s\npartition = %d\n",
- dev_name, file_name, partition);
-#endif
+
+ DEBUG_F("dev_path = %s\nfile_name = %s\npartition = %d\n",
+ spec->dev, spec->file, partition);
+
/* Find OF device phandle */
- dev = prom_finddevice(dev_name);
+ dev = prom_finddevice(spec->dev);
if (dev == PROM_INVALID_HANDLE) {
- prom_printf("device not found !\n");
- return FILE_ERR_NOTFOUND;
+ return FILE_ERR_BADDEV;
}
-#if DEBUG
- prom_printf("dev_phandle = %08lx\n", dev);
-#endif
+
+ DEBUG_F("dev_phandle = %p\n", dev);
+
/* Check the kind of device */
result = prom_getprop(dev, "device_type", temps, 63);
if (result == -1) {
prom_printf("can't get <device_type> for device\n");
- return FILE_ERR_NOTFOUND;
+ return FILE_ERR_BADDEV;
}
temps[result] = 0;
if (!strcmp(temps, "block"))
file->device_kind = FILE_DEVICE_NET;
else {
prom_printf("Unkown device type <%s>\n", temps);
- return FILE_ERR_NOTFOUND;
+ return FILE_ERR_BADDEV;
}
switch(file->device_kind) {
case FILE_DEVICE_BLOCK:
-#if DEBUG
- prom_printf("device is a block device\n");
-#endif
- return file_block_open(file, dev_name, file_name, partition);
+ DEBUG_F("device is a block device\n");
+ return file_block_open(file, spec->dev, spec->file, partition);
case FILE_DEVICE_NET:
-#if DEBUG
- prom_printf("device is a network device\n");
-#endif
- return file_net_open(file, dev_name, file_name);
+ DEBUG_F("device is a network device\n");
+ return file_net_open(file, spec->dev, spec->file);
}
return 0;
}
+
+/*
+ * Local variables:
+ * c-file-style: "K&R"
+ * c-basic-offset: 5
+ * End:
+ */
#include "stdlib.h"
#include "fs.h"
+#include "errors.h"
extern const struct fs_t of_filesystem;
extern const struct fs_t of_net_filesystem;
extern const struct fs_t ext2_filesystem;
-extern const struct fs_t reiserfs_filesystem;
//extern const struct fs_t iso_filesystem;
+/* Configurable filesystems */
+
+#ifdef CONFIG_FS_XFS
+extern const struct fs_t xfs_filesystem;
+#endif /* CONFIG_FS_XFS */
+
+#ifdef CONFIG_FS_REISERFS
+extern const struct fs_t reiserfs_filesystem;
+#endif /* CONFIG_FS_REISERFS */
+
/* Filesystem handlers yaboot knows about */
static const struct fs_t *block_filesystems[] = {
&ext2_filesystem, /* ext2 */
+#ifdef CONFIG_FS_XFS
+ &xfs_filesystem, /* XFS */
+#endif /* CONFIG_FS_XFS */
+#ifdef CONFIG_FS_REISERFS
&reiserfs_filesystem, /* reiserfs */
+#endif /* CONFIG_FS_REISERFS */
&of_filesystem, /* HFS/HFS+, ISO9660, UDF, UFS */
NULL
};
const struct fs_t *fs_of_netboot = &of_net_filesystem; /* needed by file.c */
const struct fs_t *
-fs_open( struct boot_file_t *file, const char *dev_name,
- struct partition_t *part, const char *file_name)
+fs_open(struct boot_file_t *file, const char *dev_name,
+ struct partition_t *part, const char *file_name)
{
- const struct fs_t **fs;
- for( fs = block_filesystems; *fs; fs++ )
- if( (*fs)->open( file, dev_name, part, file_name ) == FILE_ERR_OK )
- break;
+ const struct fs_t **fs;
+ for (fs = block_filesystems; *fs; fs++)
+ if ((fserrorno = (*fs)->open(file, dev_name, part, file_name)) != FILE_ERR_BAD_FSYS)
+ break;
- return *fs;
+ return *fs;
}
#include "string.h"
#include "partition.h"
#include "fs.h"
+#include "errors.h"
#define FAST_VERSION
#define MAX_READ_RANGE 256
const char* file_name)
{
int result = 0;
+ int error = FILE_ERR_NOTFOUND;
static char buffer[1024];
int ofopened = 0;
if (opened) {
prom_printf("ext2_open() : fs busy\n");
- return FILE_ERR_NOTFOUND;
+ DEBUG_LEAVE(FILE_ERR_FSBUSY);
+ return FILE_ERR_FSBUSY;
}
if (file->device_kind != FILE_DEVICE_BLOCK) {
prom_printf("Can't open ext2 filesystem on non-block device\n");
- return FILE_ERR_NOTFOUND;
+ DEBUG_LEAVE(FILE_ERR_BADDEV);
+ return FILE_ERR_BADDEV;
}
fs = NULL;
cur_file = file;
- DEBUG_F("partition offset: %d\n", doff);
+ DEBUG_F("partition offset: %Lu\n", doff);
/* Open the OF device for the entire disk */
strncpy(buffer, dev_name, 1020);
file->of_device = prom_open(buffer);
- DEBUG_F("file->of_device = %08lx\n", file->of_device);
+ DEBUG_F("file->of_device = %p\n", file->of_device);
if (file->of_device == PROM_INVALID_HANDLE) {
- DEBUG_F("Can't open device %s\n", file->of_device);
-
- return FILE_ERR_NOTFOUND;
+ DEBUG_F("Can't open device %p\n", file->of_device);
+ DEBUG_LEAVE(FILE_IOERR);
+ return FILE_IOERR;
}
ofopened = 1;
if(result == EXT2_ET_BAD_MAGIC)
{
- DEBUG_F( "ext2fs_open returned bad magic loading file %s\n",
+ DEBUG_F( "ext2fs_open returned bad magic loading file %p\n",
file );
}
else
DEBUG_F( "ext2fs_open error #%d while loading file %s\n",
result, file_name);
}
-
+ error = FILE_ERR_BAD_FSYS;
goto bail;
}
if (!block_buffer) {
DEBUG_F("ext2fs: can't alloc block buffer (%d bytes)\n", fs->blocksize * 2);
-
+ error = FILE_IOERR;
goto bail;
}
if (result) {
DEBUG_F("ext2fs_namei error #%d while loading file %s\n", result, file_name);
+ if (result == EXT2_ET_SYMLINK_LOOP)
+ error = FILE_ERR_SYMLINK_LOOP;
+ else if (result == EXT2_ET_FILE_NOT_FOUND)
+ error = FILE_ERR_NOTFOUND;
+ else
+ error = FILE_IOERR;
goto bail;
}
if (result) {
DEBUG_F("ext2fs_follow_link error #%d while loading file %s\n", result, file_name);
-
+ error = FILE_ERR_NOTFOUND;
goto bail;
}
#endif
if (result) {
DEBUG_F("ext2fs_read_inode error #%d while loading file %s\n", result, file_name);
-
+ if (result == EXT2_ET_FILE_TOO_BIG)
+ error = FILE_ERR_LENGTH;
+ else if (result == EXT2_ET_LLSEEK_FAILED)
+ error = FILE_CANT_SEEK;
+ else if (result == EXT2_ET_FILE_NOT_FOUND)
+ error = FILE_ERR_NOTFOUND;
+ else
+ error = FILE_IOERR;
goto bail;
}
#endif /* FAST_VERSION */
block_buffer = NULL;
cur_file = NULL;
- DEBUG_LEAVE(FILE_ERR_NOTFOUND);
- return FILE_ERR_NOTFOUND;
+ DEBUG_LEAVE_F(error);
+ return error;
}
DEBUG_LEAVE(FILE_ERR_OK);
#ifdef FAST_VERSION
if (!opened)
- return FILE_ERR_NOTFOUND;
+ return FILE_IOERR;
- DEBUG_F("ext_read() from pos 0x%x, size: 0x%x\n", file->pos, size);
+ DEBUG_F("ext_read() from pos 0x%Lx, size: 0x%ux\n", file->pos, size);
read_cur_file = file;
retval = read_result;
}
if (retval)
- prom_printf ("ext2: i/o error %d in read\n", retval);
+ prom_printf ("ext2: i/o error %ld in read\n", (long) retval);
return read_total;
unsigned int read = 0;
if (!opened)
- return FILE_ERR_NOTFOUND;
+ return FILE_IOERR;
DEBUG_F("ext_read() from pos 0x%x, size: 0x%x\n", file->pos, size);
unsigned int newpos)
{
if (!opened)
- return FILE_ERR_NOTFOUND;
+ return FILE_CANT_SEEK;
file->pos = newpos;
return FILE_ERR_OK;
ext2_close( struct boot_file_t* file)
{
if (!opened)
- return FILE_ERR_NOTFOUND;
+ return FILE_IOERR;
if (block_buffer)
free(block_buffer);
fs = NULL;
prom_close(file->of_device);
+ DEBUG_F("ext2_close called\n");
opened = 0;
size = (count < 0) ? -count : count * bs;
prom_lseek(cur_file->of_device, tempb);
if (prom_read(cur_file->of_device, data, size) != size) {
- prom_printf ("\nRead error on block %d", block);
+ DEBUG_F("\nRead error on block %ld\n", block);
return EXT2_ET_SHORT_READ;
}
return 0;
{
return 0;
}
-
#include "string.h"
#include "partition.h"
#include "fs.h"
-
+#include "errors.h"
static int iso_open( struct boot_file_t* file,
const char* dev_name,
struct partition_t* part,
const char* file_name)
{
- return FILE_ERR_NOTFOUND;
+ return FILE_ERR_BAD_FSYS;
}
static int
unsigned int size,
void* buffer)
{
- return FILE_ERR_NOTFOUND;
+ return FILE_ERR_BAD_FSYS;
}
static int
iso_seek( struct boot_file_t* file,
unsigned int newpos)
{
- return FILE_ERR_NOTFOUND;
+ return FILE_ERR_BAD_FSYS;
}
static int
#include "string.h"
#include "partition.h"
#include "fs.h"
-
+#include "errors.h"
#define LOAD_BUFFER_POS 0x600000
#define LOAD_BUFFER_SIZE 0x400000
-static int of_open( struct boot_file_t* file,
- const char* dev_name,
- struct partition_t* part,
- const char* file_name);
-static int of_read( struct boot_file_t* file,
- unsigned int size,
- void* buffer);
-static int of_seek( struct boot_file_t* file,
- unsigned int newpos);
-static int of_close( struct boot_file_t* file);
-
-
-static int of_net_open( struct boot_file_t* file,
- const char* dev_name,
- struct partition_t* part,
- const char* file_name);
-static int of_net_read( struct boot_file_t* file,
- unsigned int size,
- void* buffer);
-static int of_net_seek( struct boot_file_t* file,
- unsigned int newpos);
+static int of_open(struct boot_file_t* file, const char* dev_name,
+ struct partition_t* part, const char* file_name);
+static int of_read(struct boot_file_t* file, unsigned int size, void* buffer);
+static int of_seek(struct boot_file_t* file, unsigned int newpos);
+static int of_close(struct boot_file_t* file);
+
+
+static int of_net_open(struct boot_file_t* file, const char* dev_name,
+ struct partition_t* part, const char* file_name);
+static int of_net_read(struct boot_file_t* file, unsigned int size, void* buffer);
+static int of_net_seek(struct boot_file_t* file, unsigned int newpos);
struct fs_t of_filesystem =
{
- "built-in",
- of_open,
- of_read,
- of_seek,
- of_close
+ "built-in",
+ of_open,
+ of_read,
+ of_seek,
+ of_close
};
struct fs_t of_net_filesystem =
{
- "built-in network",
- of_net_open,
- of_net_read,
- of_net_seek,
- of_close
+ "built-in network",
+ of_net_open,
+ of_net_read,
+ of_net_seek,
+ of_close
};
-
-
static int
-of_open( struct boot_file_t* file,
- const char* dev_name,
- struct partition_t* part,
- const char* file_name)
+of_open(struct boot_file_t* file, const char* dev_name,
+ struct partition_t* part, const char* file_name)
{
- static char buffer[1024];
+ static char buffer[1024];
+ char *filename;
+ char *p;
- DEBUG_ENTER;
- DEBUG_OPEN;
-
- strncpy(buffer, dev_name, 1000);
- strcat(buffer, ":");
- if (part) {
- char pn[3];
- sprintf(pn, "%02d", part->part_number);
- strcat(buffer, pn);
- }
- if (file_name && strlen(file_name)) {
- if (part)
- strcat(buffer, ",");
- strcat(buffer, file_name);
- }
-
- DEBUG_F("<%s>\n", buffer);
-
- file->of_device = prom_open(buffer);
-
- DEBUG_F("file->of_device = %08lx\n", file->of_device);
-
- file->pos = 0;
- file->buffer = NULL;
- if ((file->of_device == PROM_INVALID_HANDLE) || (file->of_device == 0))
- {
- DEBUG_LEAVE(FILE_ERR_NOTFOUND);
- return FILE_ERR_NOTFOUND;
- }
+ DEBUG_ENTER;
+ DEBUG_OPEN;
+
+ strncpy(buffer, dev_name, 768);
+ strcat(buffer, ":");
+ if (part) {
+ char pn[3];
+ sprintf(pn, "%02d", part->part_number);
+ strcat(buffer, pn);
+ }
+ if (file_name && strlen(file_name)) {
+ if (part)
+ strcat(buffer, ",");
+ filename = strdup(file_name);
+ for (p = filename; *p; p++)
+ if (*p == '/')
+ *p = '\\';
+ strcat(buffer, filename);
+ free(filename);
+ }
+
+ DEBUG_F("opening: \"%s\"\n", buffer);
+
+ file->of_device = prom_open(buffer);
+
+ DEBUG_F("file->of_device = %p\n", file->of_device);
+
+ file->pos = 0;
+ file->buffer = NULL;
+ if ((file->of_device == PROM_INVALID_HANDLE) || (file->of_device == 0))
+ {
+ DEBUG_LEAVE(FILE_ERR_BAD_FSYS);
+ return FILE_ERR_BAD_FSYS;
+ }
- DEBUG_LEAVE(FILE_ERR_OK);
- return FILE_ERR_OK;
+ DEBUG_LEAVE(FILE_ERR_OK);
+ return FILE_ERR_OK;
}
static int
-of_net_open( struct boot_file_t* file,
- const char* dev_name,
- struct partition_t* part,
- const char* file_name)
+of_net_open(struct boot_file_t* file, const char* dev_name,
+ struct partition_t* part, const char* file_name)
{
- static char buffer[1024];
-
- DEBUG_ENTER;
- DEBUG_OPEN;
-
- strncpy(buffer, dev_name, 1000);
- strcat(buffer, ":0");
- if (file_name && strlen(file_name)) {
- strcat(buffer, ",");
- strcat(buffer, file_name);
- }
+ static char buffer[1024];
+ char *filename;
+ char *p;
+
+ DEBUG_ENTER;
+ DEBUG_OPEN;
+
+ strncpy(buffer, dev_name, 768);
+ if (file_name && strlen(file_name)) {
+ strcat(buffer, ",");
+ filename = strdup(file_name);
+ for (p = filename; *p; p++)
+ if (*p == '/')
+ *p = '\\';
+ strcat(buffer, filename);
+ free(filename);
+ }
- DEBUG_F("<%s>\n", buffer);
+ DEBUG_F("Opening: \"%s\"\n", buffer);
- file->of_device = prom_open(buffer);
+ file->of_device = prom_open(buffer);
- DEBUG_F("file->of_device = %08lx\n", file->of_device);
+ DEBUG_F("file->of_device = %p\n", file->of_device);
- file->pos = 0;
- if ((file->of_device == PROM_INVALID_HANDLE) || (file->of_device == 0))
- {
- DEBUG_LEAVE(FILE_ERR_NOTFOUND);
- return FILE_ERR_NOTFOUND;
- }
+ file->pos = 0;
+ if ((file->of_device == PROM_INVALID_HANDLE) || (file->of_device == 0))
+ {
+ DEBUG_LEAVE(FILE_ERR_BAD_FSYS);
+ return FILE_ERR_BAD_FSYS;
+ }
- file->buffer = prom_claim((void *)LOAD_BUFFER_POS, LOAD_BUFFER_SIZE, 0);
- if (file->buffer == (void *)-1) {
- prom_printf("Can't claim memory for TFTP download\n");
- prom_close(file->of_device);
- DEBUG_LEAVE(FILE_ERR_NOTFOUND);
- return FILE_ERR_NOTFOUND;
- }
- memset(file->buffer, 0, LOAD_BUFFER_SIZE);
-
- DEBUG_F("TFP...\n");
-
- file->len = prom_loadmethod(file->of_device, file->buffer);
+ file->buffer = prom_claim((void *)LOAD_BUFFER_POS, LOAD_BUFFER_SIZE, 0);
+ if (file->buffer == (void *)-1) {
+ prom_printf("Can't claim memory for TFTP download\n");
+ prom_close(file->of_device);
+ DEBUG_LEAVE(FILE_IOERR);
+ return FILE_IOERR;
+ }
+ memset(file->buffer, 0, LOAD_BUFFER_SIZE);
+
+ DEBUG_F("TFP...\n");
+
+ file->len = prom_loadmethod(file->of_device, file->buffer);
- DEBUG_F("result: %d\n", file->len);
-
+ DEBUG_F("result: %Ld\n", file->len);
- DEBUG_LEAVE(FILE_ERR_OK);
- return FILE_ERR_OK;
+ DEBUG_LEAVE(FILE_ERR_OK);
+ return FILE_ERR_OK;
}
static int
-of_read( struct boot_file_t* file,
- unsigned int size,
- void* buffer)
+of_read(struct boot_file_t* file, unsigned int size, void* buffer)
{
- unsigned int count;
+ unsigned int count;
- count = prom_read(file->of_device, buffer, size);
- file->pos += count;
- return count;
+ count = prom_read(file->of_device, buffer, size);
+ file->pos += count;
+ return count;
}
static int
-of_net_read( struct boot_file_t* file,
- unsigned int size,
- void* buffer)
+of_net_read(struct boot_file_t* file, unsigned int size, void* buffer)
{
- unsigned int count, av;
+ unsigned int count, av;
- av = file->len - file->pos;
- count = size > av ? av : size;
- memcpy(buffer, file->buffer + file->pos, count);
- file->pos += count;
- return count;
+ av = file->len - file->pos;
+ count = size > av ? av : size;
+ memcpy(buffer, file->buffer + file->pos, count);
+ file->pos += count;
+ return count;
}
static int
-of_seek( struct boot_file_t* file,
- unsigned int newpos)
+of_seek(struct boot_file_t* file, unsigned int newpos)
{
- if (prom_seek(file->of_device, newpos)) {
- file->pos = newpos;
- return FILE_ERR_OK;
- }
+ if (prom_seek(file->of_device, newpos)) {
+ file->pos = newpos;
+ return FILE_ERR_OK;
+ }
- return FILE_CANT_SEEK;
+ return FILE_CANT_SEEK;
}
static int
-of_net_seek( struct boot_file_t* file,
- unsigned int newpos)
+of_net_seek(struct boot_file_t* file, unsigned int newpos)
{
- file->pos = (newpos > file->len) ? file->len : newpos;
- return FILE_ERR_OK;
+ file->pos = (newpos > file->len) ? file->len : newpos;
+ return FILE_ERR_OK;
}
static int
-of_close( struct boot_file_t* file)
+of_close(struct boot_file_t* file)
{
- DEBUG_ENTER;
- DEBUG_F("<@0x%08lx>n", file->of_device);
+ DEBUG_ENTER;
+ DEBUG_F("<@%p>\n", file->of_device);
- if (file->buffer) {
- prom_release(file->buffer, LOAD_BUFFER_SIZE);
- }
- prom_close(file->of_device);
+ if (file->buffer) {
+ prom_release(file->buffer, LOAD_BUFFER_SIZE);
+ }
+ prom_close(file->of_device);
+ DEBUG_F("of_close called\n");
- DEBUG_LEAVE(0);
-
- return 0;
+ DEBUG_LEAVE(0);
+ return 0;
}
+/*
+ * Local variables:
+ * c-file-style: "K&R"
+ * c-basic-offset: 5
+ * End:
+ */
#include "string.h"
#include "stdlib.h"
#include "fs.h"
+#include "errors.h"
#include "reiserfs/reiserfs.h"
/* Exported in struct fs_t */
static int reiserfs_open( struct boot_file_t *file, const char *dev_name,
- struct partition_t *part, const char *file_name );
+ struct partition_t *part, const char *file_name );
static int reiserfs_read( struct boot_file_t *file, unsigned int size,
- void *buffer );
+ void *buffer );
static int reiserfs_seek( struct boot_file_t *file, unsigned int newpos );
static int reiserfs_close( struct boot_file_t *file );
struct fs_t reiserfs_filesystem = {
- name:"reiserfs",
- open:reiserfs_open,
- read:reiserfs_read,
- seek:reiserfs_seek,
- close:reiserfs_close
+ name:"reiserfs",
+ open:reiserfs_open,
+ read:reiserfs_read,
+ seek:reiserfs_seek,
+ close:reiserfs_close
};
static int reiserfs_read_super( void );
reiserfs_open( struct boot_file_t *file, const char *dev_name,
struct partition_t *part, const char *file_name )
{
- static char buffer[1024];
-
- DEBUG_ENTER;
- DEBUG_OPEN;
-
- memset( INFO, 0, sizeof(struct reiserfs_state) );
- INFO->file = file;
-
- if (part)
- {
- DEBUG_F( "Determining offset for partition %d\n", part->part_number );
- INFO->partition_offset = ((__u64)(part->part_start)) * ((__u64)part->blocksize);
- DEBUG_F( "%Lu = %lu * %hu\n", INFO->partition_offset,
- part->part_start,
- part->blocksize );
- }
- else
- INFO->partition_offset = 0;
-
- sprintf( buffer, "%s:%d", dev_name, /*part ? part->part_number :*/ 0 );
- file->of_device = prom_open( buffer );
- DEBUG_F( "Trying to open dev_name=%s; filename=%s; partition offset=%Lu\n",
- buffer, file_name, INFO->partition_offset );
-
- if ( file->of_device == PROM_INVALID_HANDLE || file->of_device == NULL )
- {
- DEBUG_F( "Can't open device %s\n", file->of_device );
- DEBUG_LEAVE(FILE_ERR_NOTFOUND);
- return FILE_ERR_NOTFOUND;
- }
-
- DEBUG_F( "%s was successfully opened\n" );
-
- if ( reiserfs_read_super() != 1 )
- {
- DEBUG_F( "Couldn't open ReiserFS @ %s/%Lu\n", buffer, INFO->partition_offset );
- prom_close( file->of_device );
- DEBUG_LEAVE(FILE_ERR_NOTFOUND);
- return FILE_ERR_NOTFOUND;
- }
-
- DEBUG_F( "Attempting to open %s\n", file_name );
- strcpy(buffer, file_name); /* reiserfs_open_file modifies argument */
- if( reiserfs_open_file(buffer) == 0 )
- {
- DEBUG_F( "reiserfs_open_file failed. errnum = %d\n", errnum );
- prom_close( file->of_device );
- DEBUG_LEAVE(FILE_ERR_NOTFOUND);
- return FILE_ERR_NOTFOUND;
- }
-
- DEBUG_F( "Successfully opened %s\n", file_name );
-
- DEBUG_LEAVE(FILE_ERR_OK);
- return FILE_ERR_OK;
+ static char buffer[1024];
+
+ DEBUG_ENTER;
+ DEBUG_OPEN;
+
+ memset( INFO, 0, sizeof(struct reiserfs_state) );
+ INFO->file = file;
+
+ if (part)
+ {
+ DEBUG_F( "Determining offset for partition %d\n", part->part_number );
+ INFO->partition_offset = ((__u64)(part->part_start)) * ((__u64)part->blocksize);
+ DEBUG_F( "%Lu = %lu * %hu\n", INFO->partition_offset,
+ part->part_start,
+ part->blocksize );
+ }
+ else
+ INFO->partition_offset = 0;
+
+ sprintf( buffer, "%s:%d", dev_name, 0 ); /* 0 is full disk in OF */
+ file->of_device = prom_open( buffer );
+ DEBUG_F( "Trying to open dev_name=%s; filename=%s; partition offset=%Lu\n",
+ buffer, file_name, INFO->partition_offset );
+
+ if ( file->of_device == PROM_INVALID_HANDLE || file->of_device == NULL )
+ {
+ DEBUG_F( "Can't open device %p\n", file->of_device );
+ DEBUG_LEAVE(FILE_ERR_BADDEV);
+ return FILE_ERR_BADDEV;
+ }
+
+ DEBUG_F("%p was successfully opened\n", file->of_device);
+
+ if ( reiserfs_read_super() != 1 )
+ {
+ DEBUG_F( "Couldn't open ReiserFS @ %s/%Lu\n", buffer, INFO->partition_offset );
+ prom_close( file->of_device );
+ DEBUG_LEAVE(FILE_ERR_BAD_FSYS);
+ return FILE_ERR_BAD_FSYS;
+ }
+
+ DEBUG_F( "Attempting to open %s\n", file_name );
+ strcpy(buffer, file_name); /* reiserfs_open_file modifies argument */
+ if (reiserfs_open_file(buffer) == 0)
+ {
+ DEBUG_F( "reiserfs_open_file failed. errnum = %d\n", errnum );
+ prom_close( file->of_device );
+ DEBUG_LEAVE_F(errnum);
+ return errnum;
+ }
+
+ DEBUG_F( "Successfully opened %s\n", file_name );
+
+ DEBUG_LEAVE(FILE_ERR_OK);
+ DEBUG_SLEEP;
+ return FILE_ERR_OK;
}
static int
reiserfs_read( struct boot_file_t *file, unsigned int size, void *buffer )
{
- return reiserfs_read_data( buffer, size );
+ return reiserfs_read_data( buffer, size );
}
static int
reiserfs_seek( struct boot_file_t *file, unsigned int newpos )
{
- file->pos = newpos;
- return FILE_ERR_OK;
+ file->pos = newpos;
+ return FILE_ERR_OK;
}
static int
reiserfs_close( struct boot_file_t *file )
{
- if( file->of_device )
- {
- prom_close(file->of_device);
- file->of_device = 0;
- }
- return FILE_ERR_OK;
+ if( file->of_device )
+ {
+ prom_close(file->of_device);
+ file->of_device = 0;
+ DEBUG_F("reiserfs_close called\n");
+ }
+ return FILE_ERR_OK;
}
static __inline__ __u32
log2( __u32 word )
{
- int i = 0;
- while( word && (word & (1 << ++i)) == 0 );
- return i;
+ int i = 0;
+ while( word && (word & (1 << ++i)) == 0 );
+ return i;
}
static __inline__ int
is_power_of_two( unsigned long word )
{
- return ( word & -word ) == word;
+ return ( word & -word ) == word;
}
static int
read_disk_block( struct boot_file_t *file, __u32 block, __u32 start,
__u32 length, void *buf )
{
- __u16 fs_blocksize = INFO->blocksize == 0 ? REISERFS_OLD_BLOCKSIZE
- : INFO->blocksize;
- unsigned long long pos = block * fs_blocksize;
- pos += INFO->partition_offset + start;
- DEBUG_F( "Reading %lu bytes, starting at block %lu, disk offset %Lu\n",
- length, block, pos );
- prom_lseek( file->of_device, pos );
- return prom_read( file->of_device, buf, length );
+ __u16 fs_blocksize = INFO->blocksize == 0 ? REISERFS_OLD_BLOCKSIZE
+ : INFO->blocksize;
+ unsigned long long pos = block * fs_blocksize;
+ pos += INFO->partition_offset + start;
+ DEBUG_F( "Reading %u bytes, starting at block %u, disk offset %Lu\n",
+ length, block, pos );
+ if (!prom_lseek( file->of_device, pos )) {
+ DEBUG_F("prom_lseek failed\n");
+ return 0;
+ }
+ return prom_read( file->of_device, buf, length );
}
static int
journal_read( __u32 block, __u32 len, char *buffer )
{
- return read_disk_block( INFO->file,
- (INFO->journal_block + block), 0,
- len, buffer );
+ return read_disk_block( INFO->file,
+ (INFO->journal_block + block), 0,
+ len, buffer );
}
/* Read a block from ReiserFS file system, taking the journal into
static int
block_read( __u32 blockNr, __u32 start, __u32 len, char *buffer )
{
- __u32 transactions = INFO->journal_transactions;
- __u32 desc_block = INFO->journal_first_desc;
- __u32 journal_mask = INFO->journal_block_count - 1;
- __u32 translatedNr = blockNr;
- __u32 *journal_table = JOURNAL_START;
+ __u32 transactions = INFO->journal_transactions;
+ __u32 desc_block = INFO->journal_first_desc;
+ __u32 journal_mask = INFO->journal_block_count - 1;
+ __u32 translatedNr = blockNr;
+ __u32 *journal_table = JOURNAL_START;
// DEBUG_F( "block_read( %u, %u, %u, ..)\n", blockNr, start, len );
- while ( transactions-- > 0 )
- {
- int i = 0;
- int j_len;
-
- if ( *journal_table != 0xffffffff )
- {
- /* Search for the blockNr in cached journal */
- j_len = le32_to_cpu(*journal_table++);
- while ( i++ < j_len )
- {
- if ( le32_to_cpu(*journal_table++) == blockNr )
- {
- journal_table += j_len - i;
- goto found;
- }
- }
- }
- else
- {
- /* This is the end of cached journal marker. The remaining
- * transactions are still on disk. */
- struct reiserfs_journal_desc desc;
- struct reiserfs_journal_commit commit;
-
- if ( !journal_read( desc_block, sizeof(desc), (char *) &desc ) )
- return 0;
-
- j_len = le32_to_cpu(desc.j_len);
- while ( i < j_len && i < JOURNAL_TRANS_HALF )
- if ( le32_to_cpu(desc.j_realblock[i++]) == blockNr )
- goto found;
+ while ( transactions-- > 0 )
+ {
+ int i = 0;
+ int j_len;
+
+ if ( *journal_table != 0xffffffff )
+ {
+ /* Search for the blockNr in cached journal */
+ j_len = le32_to_cpu(*journal_table++);
+ while ( i++ < j_len )
+ {
+ if ( le32_to_cpu(*journal_table++) == blockNr )
+ {
+ journal_table += j_len - i;
+ goto found;
+ }
+ }
+ }
+ else
+ {
+ /* This is the end of cached journal marker. The remaining
+ * transactions are still on disk. */
+ struct reiserfs_journal_desc desc;
+ struct reiserfs_journal_commit commit;
+
+ if ( !journal_read( desc_block, sizeof(desc), (char *) &desc ) )
+ return 0;
- if ( j_len >= JOURNAL_TRANS_HALF )
- {
- int commit_block = ( desc_block + 1 + j_len ) & journal_mask;
+ j_len = le32_to_cpu(desc.j_len);
+ while ( i < j_len && i < JOURNAL_TRANS_HALF )
+ if ( le32_to_cpu(desc.j_realblock[i++]) == blockNr )
+ goto found;
- if ( !journal_read( commit_block,
- sizeof(commit), (char *) &commit ) )
- return 0;
+ if ( j_len >= JOURNAL_TRANS_HALF )
+ {
+ int commit_block = ( desc_block + 1 + j_len ) & journal_mask;
+
+ if ( !journal_read( commit_block,
+ sizeof(commit), (char *) &commit ) )
+ return 0;
- while ( i < j_len )
- if ( le32_to_cpu(commit.j_realblock[i++ - JOURNAL_TRANS_HALF]) == blockNr )
- goto found;
- }
- }
- goto not_found;
+ while ( i < j_len )
+ if ( le32_to_cpu(commit.j_realblock[i++ - JOURNAL_TRANS_HALF]) == blockNr )
+ goto found;
+ }
+ }
+ goto not_found;
- found:
- translatedNr =
- INFO->journal_block + ( ( desc_block + i ) & journal_mask );
+ found:
+ translatedNr =
+ INFO->journal_block + ( ( desc_block + i ) & journal_mask );
- DEBUG_F( "block_read: block %u is mapped to journal block %u.\n",
- blockNr, translatedNr - INFO->journal_block );
+ DEBUG_F( "block_read: block %u is mapped to journal block %u.\n",
+ blockNr, translatedNr - INFO->journal_block );
- /* We must continue the search, as this block may be overwritten in
- * later transactions. */
- not_found:
- desc_block = (desc_block + 2 + j_len) & journal_mask;
- }
+ /* We must continue the search, as this block may be overwritten in
+ * later transactions. */
+ not_found:
+ desc_block = (desc_block + 2 + j_len) & journal_mask;
+ }
- return read_disk_block( INFO->file, translatedNr, start, len, buffer );
+ return read_disk_block( INFO->file, translatedNr, start, len, buffer );
}
/* Init the journal data structure. We try to cache as much as
static int
journal_init( void )
{
- struct reiserfs_journal_header header;
- struct reiserfs_journal_desc desc;
- struct reiserfs_journal_commit commit;
- __u32 block_count = INFO->journal_block_count;
- __u32 desc_block;
- __u32 commit_block;
- __u32 next_trans_id;
- __u32 *journal_table = JOURNAL_START;
-
- journal_read( block_count, sizeof ( header ), ( char * ) &header );
- desc_block = le32_to_cpu(header.j_first_unflushed_offset);
- if ( desc_block >= block_count )
- return 0;
-
- INFO->journal_transactions = 0;
- INFO->journal_first_desc = desc_block;
- next_trans_id = le32_to_cpu(header.j_last_flush_trans_id) + 1;
-
- DEBUG_F( "journal_init: last flushed %u\n", le32_to_cpu(header.j_last_flush_trans_id) );
-
- while ( 1 )
- {
- journal_read( desc_block, sizeof(desc), (char *) &desc );
- if ( strcmp( JOURNAL_DESC_MAGIC, desc.j_magic ) != 0
- || desc.j_trans_id != next_trans_id
- || desc.j_mount_id != header.j_mount_id )
- /* no more valid transactions */
- break;
-
- commit_block = ( desc_block + le32_to_cpu(desc.j_len) + 1 ) & ( block_count - 1 );
- journal_read( commit_block, sizeof(commit), (char *) &commit );
- if ( desc.j_trans_id != commit.j_trans_id
- || desc.j_len != commit.j_len )
- /* no more valid transactions */
- break;
-
-
- DEBUG_F( "Found valid transaction %u/%u at %u.\n",
- le32_to_cpu(desc.j_trans_id), le32_to_cpu(desc.j_mount_id),
- desc_block );
-
-
- next_trans_id++;
- if ( journal_table < JOURNAL_END )
- {
- if ( ( journal_table + 1 + le32_to_cpu(desc.j_len) ) >= JOURNAL_END )
- {
- /* The table is almost full; mark the end of the cached * *
- * journal. */
- *journal_table = 0xffffffff;
- journal_table = JOURNAL_END;
- }
- else
- {
- int i;
-
- /* Cache the length and the realblock numbers in the table. *
- * The block number of descriptor can easily be computed. *
- * and need not to be stored here. */
- *journal_table++ = desc.j_len;
- for ( i = 0; i < le32_to_cpu(desc.j_len) && i < JOURNAL_TRANS_HALF; i++ )
- {
- *journal_table++ = desc.j_realblock[i];
-
- DEBUG_F( "block %u is in journal %u.\n",
- le32_to_cpu(desc.j_realblock[i]), desc_block );
-
- }
- for ( ; i < le32_to_cpu(desc.j_len); i++ )
- {
- *journal_table++ =
- commit.j_realblock[i - JOURNAL_TRANS_HALF];
-
- DEBUG_F( "block %u is in journal %u.\n",
- le32_to_cpu(commit.j_realblock[i - JOURNAL_TRANS_HALF]),
- desc_block );
-
- }
- }
- }
- desc_block = (commit_block + 1) & (block_count - 1);
- }
-
- DEBUG_F( "Transaction %u/%u at %u isn't valid.\n",
- le32_to_cpu(desc.j_trans_id), le32_to_cpu(desc.j_mount_id),
- desc_block );
-
-
- INFO->journal_transactions
- = next_trans_id - le32_to_cpu(header.j_last_flush_trans_id) - 1;
- return errnum == 0;
+ struct reiserfs_journal_header header;
+ struct reiserfs_journal_desc desc;
+ struct reiserfs_journal_commit commit;
+ __u32 block_count = INFO->journal_block_count;
+ __u32 desc_block;
+ __u32 commit_block;
+ __u32 next_trans_id;
+ __u32 *journal_table = JOURNAL_START;
+
+ journal_read( block_count, sizeof ( header ), ( char * ) &header );
+ desc_block = le32_to_cpu(header.j_first_unflushed_offset);
+ if ( desc_block >= block_count )
+ return 0;
+
+ INFO->journal_transactions = 0;
+ INFO->journal_first_desc = desc_block;
+ next_trans_id = le32_to_cpu(header.j_last_flush_trans_id) + 1;
+
+ DEBUG_F( "journal_init: last flushed %u\n", le32_to_cpu(header.j_last_flush_trans_id) );
+
+ while ( 1 )
+ {
+ journal_read( desc_block, sizeof(desc), (char *) &desc );
+ if ( strcmp( JOURNAL_DESC_MAGIC, desc.j_magic ) != 0
+ || desc.j_trans_id != next_trans_id
+ || desc.j_mount_id != header.j_mount_id )
+ /* no more valid transactions */
+ break;
+
+ commit_block = ( desc_block + le32_to_cpu(desc.j_len) + 1 ) & ( block_count - 1 );
+ journal_read( commit_block, sizeof(commit), (char *) &commit );
+ if ( desc.j_trans_id != commit.j_trans_id
+ || desc.j_len != commit.j_len )
+ /* no more valid transactions */
+ break;
+
+
+ DEBUG_F( "Found valid transaction %u/%u at %u.\n",
+ le32_to_cpu(desc.j_trans_id), le32_to_cpu(desc.j_mount_id),
+ desc_block );
+
+
+ next_trans_id++;
+ if ( journal_table < JOURNAL_END )
+ {
+ if ( ( journal_table + 1 + le32_to_cpu(desc.j_len) ) >= JOURNAL_END )
+ {
+ /* The table is almost full; mark the end of the cached * *
+ * journal. */
+ *journal_table = 0xffffffff;
+ journal_table = JOURNAL_END;
+ }
+ else
+ {
+ int i;
+
+ /* Cache the length and the realblock numbers in the table. *
+ * The block number of descriptor can easily be computed. *
+ * and need not to be stored here. */
+ *journal_table++ = desc.j_len;
+ for ( i = 0; i < le32_to_cpu(desc.j_len) && i < JOURNAL_TRANS_HALF; i++ )
+ {
+ *journal_table++ = desc.j_realblock[i];
+
+ DEBUG_F( "block %u is in journal %u.\n",
+ le32_to_cpu(desc.j_realblock[i]), desc_block );
+
+ }
+ for ( ; i < le32_to_cpu(desc.j_len); i++ )
+ {
+ *journal_table++ =
+ commit.j_realblock[i - JOURNAL_TRANS_HALF];
+
+ DEBUG_F( "block %u is in journal %u.\n",
+ le32_to_cpu(commit.j_realblock[i - JOURNAL_TRANS_HALF]),
+ desc_block );
+
+ }
+ }
+ }
+ desc_block = (commit_block + 1) & (block_count - 1);
+ }
+
+ DEBUG_F( "Transaction %u/%u at %u isn't valid.\n",
+ le32_to_cpu(desc.j_trans_id), le32_to_cpu(desc.j_mount_id),
+ desc_block );
+
+
+ INFO->journal_transactions
+ = next_trans_id - le32_to_cpu(header.j_last_flush_trans_id) - 1;
+ return (errnum == 0);
}
/* check filesystem types and read superblock into memory buffer */
static int
reiserfs_read_super( void )
{
- struct reiserfs_super_block super;
- __u64 superblock = REISERFS_SUPERBLOCK_BLOCK;
-
- read_disk_block( INFO->file, superblock, 0, sizeof(super), &super );
-
- DEBUG_F( "Found super->magic %s\n", super.s_magic );
-
- if( strcmp( REISER2FS_SUPER_MAGIC_STRING, super.s_magic ) != 0 &&
- strcmp( REISERFS_SUPER_MAGIC_STRING, super.s_magic ) != 0 )
- {
- /* Try old super block position */
- superblock = REISERFS_OLD_SUPERBLOCK_BLOCK;
- read_disk_block( INFO->file, superblock, 0, sizeof (super), &super );
-
- if ( strcmp( REISER2FS_SUPER_MAGIC_STRING, super.s_magic ) != 0 &&
- strcmp( REISERFS_SUPER_MAGIC_STRING, super.s_magic ) != 0 )
- {
- /* pre journaling super block - untested */
- if ( strcmp( REISERFS_SUPER_MAGIC_STRING,
- (char *) ((__u32) &super + 20 ) ) != 0 )
- return 0;
-
- super.s_blocksize = cpu_to_le16(REISERFS_OLD_BLOCKSIZE);
- super.s_journal_block = 0;
- super.s_version = 0;
- }
- }
-
- DEBUG_F( "ReiserFS superblock data:\n" );
- DEBUG_F( "Block count: %lu\n", le32_to_cpu(super.s_block_count) )
- DEBUG_F( "Free blocks: %lu\n", le32_to_cpu(super.s_free_blocks) );
- DEBUG_F( "Journal block: %lu\n", le32_to_cpu(super.s_journal_block) );
- DEBUG_F( "Journal size (in blocks): %lu\n",
- le32_to_cpu(super.s_orig_journal_size) );
- DEBUG_F( "Root block: %lu\n\n", le32_to_cpu(super.s_root_block) );
-
-
- INFO->version = le16_to_cpu(super.s_version);
- INFO->blocksize = le16_to_cpu(super.s_blocksize);
- INFO->blocksize_shift = log2( INFO->blocksize );
-
- INFO->journal_block = le32_to_cpu(super.s_journal_block);
- INFO->journal_block_count = le32_to_cpu(super.s_orig_journal_size);
-
- INFO->cached_slots = (FSYSREISER_CACHE_SIZE >> INFO->blocksize_shift) - 1;
-
- /* At this point, we've found a valid superblock. If we run into problems
- * mounting the FS, the user should probably know. */
-
- /* A few sanity checks ... */
- if ( INFO->version > REISERFS_MAX_SUPPORTED_VERSION )
- {
- prom_printf( "ReiserFS: Unsupported version field: %u\n",
- INFO->version );
- return 0;
- }
-
- if ( INFO->blocksize < FSYSREISER_MIN_BLOCKSIZE
- || INFO->blocksize > FSYSREISER_MAX_BLOCKSIZE )
- {
- prom_printf( "ReiserFS: Unsupported block size: %u\n",
- INFO->blocksize );
- return 0;
- }
-
- /* Setup the journal.. */
- if ( INFO->journal_block != 0 )
- {
- if ( !is_power_of_two( INFO->journal_block_count ) )
- {
- prom_printf( "ReiserFS: Unsupported journal size, "
- "not a power of 2: %lu\n",
- INFO->journal_block_count );
- return 0;
- }
-
- journal_init();
- /* Read in super block again, maybe it is in the journal */
- block_read( superblock, 0, sizeof (struct reiserfs_super_block),
- (char *) &super );
- }
-
- /* Read in the root block */
- if ( !block_read( le32_to_cpu(super.s_root_block), 0,
- INFO->blocksize, ROOT ) )
- {
- prom_printf( "ReiserFS: Failed to read in root block\n" );
- return 0;
- }
-
- /* The root node is always the "deepest", so we can
- determine the hieght of the tree using it. */
- INFO->tree_depth = blkh_level(BLOCKHEAD(ROOT));
-
-
- DEBUG_F( "root read_in: block=%u, depth=%u\n",
- le32_to_cpu(super.s_root_block), INFO->tree_depth );
-
- if ( INFO->tree_depth >= REISERFS_MAX_TREE_HEIGHT )
- {
- prom_printf( "ReiserFS: Unsupported tree depth (too deep): %u\n",
- INFO->tree_depth );
- return 0;
- }
-
- if ( INFO->tree_depth == BLKH_LEVEL_LEAF )
- {
- /* There is only one node in the whole filesystem, which is
- simultanously leaf and root */
- memcpy( LEAF, ROOT, INFO->blocksize );
- }
- return 1;
+ struct reiserfs_super_block super;
+ __u64 superblock = REISERFS_SUPERBLOCK_BLOCK;
+
+ if (read_disk_block(INFO->file, superblock, 0, sizeof(super), &super) != sizeof(super)) {
+ DEBUG_F("read_disk_block failed!\n");
+ return 0;
+ }
+
+ DEBUG_F( "Found super->magic: \"%s\"\n", super.s_magic );
+
+ if( strcmp( REISER2FS_SUPER_MAGIC_STRING, super.s_magic ) != 0 &&
+ strcmp( REISERFS_SUPER_MAGIC_STRING, super.s_magic ) != 0 )
+ {
+ /* Try old super block position */
+ superblock = REISERFS_OLD_SUPERBLOCK_BLOCK;
+
+ if (read_disk_block( INFO->file, superblock, 0, sizeof (super), &super ) != sizeof(super)) {
+ DEBUG_F("read_disk_block failed!\n");
+ return 0;
+ }
+
+ if ( strcmp( REISER2FS_SUPER_MAGIC_STRING, super.s_magic ) != 0 &&
+ strcmp( REISERFS_SUPER_MAGIC_STRING, super.s_magic ) != 0 )
+ {
+ /* pre journaling super block - untested */
+ if ( strcmp( REISERFS_SUPER_MAGIC_STRING,
+ (char *) ((__u32) &super + 20 ) ) != 0 )
+ return 0;
+
+ super.s_blocksize = cpu_to_le16(REISERFS_OLD_BLOCKSIZE);
+ super.s_journal_block = 0;
+ super.s_version = 0;
+ }
+ }
+
+ DEBUG_F( "ReiserFS superblock data:\n" );
+ DEBUG_F( "Block count: %u\n", le32_to_cpu(super.s_block_count) )
+ DEBUG_F( "Free blocks: %u\n", le32_to_cpu(super.s_free_blocks) );
+ DEBUG_F( "Journal block: %u\n", le32_to_cpu(super.s_journal_block) );
+ DEBUG_F( "Journal size (in blocks): %u\n",
+ le32_to_cpu(super.s_orig_journal_size) );
+ DEBUG_F( "Root block: %u\n\n", le32_to_cpu(super.s_root_block) );
+
+
+ INFO->version = le16_to_cpu(super.s_version);
+ INFO->blocksize = le16_to_cpu(super.s_blocksize);
+ INFO->blocksize_shift = log2( INFO->blocksize );
+
+ INFO->journal_block = le32_to_cpu(super.s_journal_block);
+ INFO->journal_block_count = le32_to_cpu(super.s_orig_journal_size);
+
+ INFO->cached_slots = (FSYSREISER_CACHE_SIZE >> INFO->blocksize_shift) - 1;
+
+ /* At this point, we've found a valid superblock. If we run into problems
+ * mounting the FS, the user should probably know. */
+
+ /* A few sanity checks ... */
+ if ( INFO->version > REISERFS_MAX_SUPPORTED_VERSION )
+ {
+ prom_printf( "ReiserFS: Unsupported version field: %u\n",
+ INFO->version );
+ return 0;
+ }
+
+ if ( INFO->blocksize < FSYSREISER_MIN_BLOCKSIZE
+ || INFO->blocksize > FSYSREISER_MAX_BLOCKSIZE )
+ {
+ prom_printf( "ReiserFS: Unsupported block size: %u\n",
+ INFO->blocksize );
+ return 0;
+ }
+
+ /* Setup the journal.. */
+ if ( INFO->journal_block != 0 )
+ {
+ if ( !is_power_of_two( INFO->journal_block_count ) )
+ {
+ prom_printf( "ReiserFS: Unsupported journal size, "
+ "not a power of 2: %u\n",
+ INFO->journal_block_count );
+ return 0;
+ }
+
+ journal_init();
+ /* Read in super block again, maybe it is in the journal */
+ block_read( superblock, 0, sizeof (struct reiserfs_super_block),
+ (char *) &super );
+ }
+
+ /* Read in the root block */
+ if ( !block_read( le32_to_cpu(super.s_root_block), 0,
+ INFO->blocksize, ROOT ) )
+ {
+ prom_printf( "ReiserFS: Failed to read in root block\n" );
+ return 0;
+ }
+
+ /* The root node is always the "deepest", so we can
+ determine the hieght of the tree using it. */
+ INFO->tree_depth = blkh_level(BLOCKHEAD(ROOT));
+
+
+ DEBUG_F( "root read_in: block=%u, depth=%u\n",
+ le32_to_cpu(super.s_root_block), INFO->tree_depth );
+
+ if ( INFO->tree_depth >= REISERFS_MAX_TREE_HEIGHT )
+ {
+ prom_printf( "ReiserFS: Unsupported tree depth (too deep): %u\n",
+ INFO->tree_depth );
+ return 0;
+ }
+
+ if ( INFO->tree_depth == BLKH_LEVEL_LEAF )
+ {
+ /* There is only one node in the whole filesystem, which is
+ simultanously leaf and root */
+ memcpy( LEAF, ROOT, INFO->blocksize );
+ }
+ return 1;
}
/***************** TREE ACCESSING METHODS *****************************/
static char *
read_tree_node( __u32 blockNr, __u16 depth )
{
- char *cache = CACHE(depth);
- int num_cached = INFO->cached_slots;
-
- if ( depth < num_cached )
- {
- /* This is the cached part of the path.
- Check if same block is needed. */
- if ( blockNr == INFO->blocks[depth] )
- return cache;
- }
- else
- cache = CACHE(num_cached);
-
- DEBUG_F( " next read_in: block=%u (depth=%u)\n", blockNr, depth );
-
- if ( !block_read( blockNr, 0, INFO->blocksize, cache ) )
- {
- DEBUG_F( "block_read failed\n" );
- return 0;
- }
-
- DEBUG_F( "FOUND: blk_level=%u, blk_nr_item=%u, blk_free_space=%u\n",
- blkh_level(BLOCKHEAD(cache)),
- blkh_nr_item(BLOCKHEAD(cache)),
- le16_to_cpu(BLOCKHEAD(cache)->blk_free_space) );
-
- /* Make sure it has the right node level */
- if ( blkh_level(BLOCKHEAD(cache)) != depth )
- {
- DEBUG_F( "depth = %u != %u\n", blkh_level(BLOCKHEAD(cache)), depth );
- DEBUG_LEAVE(FILE_ERR_BAD_FSYS);
- errnum = FILE_ERR_BAD_FSYS;
- return 0;
- }
-
- INFO->blocks[depth] = blockNr;
- return cache;
+ char *cache = CACHE(depth);
+ int num_cached = INFO->cached_slots;
+
+ if ( depth < num_cached )
+ {
+ /* This is the cached part of the path.
+ Check if same block is needed. */
+ if ( blockNr == INFO->blocks[depth] )
+ return cache;
+ }
+ else
+ cache = CACHE(num_cached);
+
+ DEBUG_F( " next read_in: block=%u (depth=%u)\n", blockNr, depth );
+
+ if ( !block_read( blockNr, 0, INFO->blocksize, cache ) )
+ {
+ DEBUG_F( "block_read failed\n" );
+ return 0;
+ }
+
+ DEBUG_F( "FOUND: blk_level=%u, blk_nr_item=%u, blk_free_space=%u\n",
+ blkh_level(BLOCKHEAD(cache)),
+ blkh_nr_item(BLOCKHEAD(cache)),
+ le16_to_cpu(BLOCKHEAD(cache)->blk_free_space) );
+
+ /* Make sure it has the right node level */
+ if ( blkh_level(BLOCKHEAD(cache)) != depth )
+ {
+ DEBUG_F( "depth = %u != %u\n", blkh_level(BLOCKHEAD(cache)), depth );
+ DEBUG_LEAVE(FILE_ERR_BAD_FSYS);
+ errnum = FILE_ERR_BAD_FSYS;
+ return 0;
+ }
+
+ INFO->blocks[depth] = blockNr;
+ return cache;
}
/* Get the next key, i.e. the key following the last retrieved key in
static int
next_key( void )
{
- __u16 depth;
- struct item_head *ih = INFO->current_ih + 1;
- char *cache;
-
-
- DEBUG_F( "next_key:\n old ih: key %u:%u:%u:%u version:%u\n",
- le32_to_cpu(INFO->current_ih->ih_key.k_dir_id),
- le32_to_cpu(INFO->current_ih->ih_key.k_objectid),
- le32_to_cpu(INFO->current_ih->ih_key.u.k_offset_v1.k_offset),
- le32_to_cpu(INFO->current_ih->ih_key.u.k_offset_v1.k_uniqueness),
- ih_version(INFO->current_ih) );
-
-
- if ( ih == &ITEMHEAD[blkh_nr_item(BLOCKHEAD( LEAF ))] )
- {
- depth = BLKH_LEVEL_LEAF;
- /* The last item, was the last in the leaf node. * Read in the next
- * * block */
- do
- {
- if ( depth == INFO->tree_depth )
- {
- /* There are no more keys at all. * Return a dummy item with
- * * MAX_KEY */
- ih =
- ( struct item_head * )
- &BLOCKHEAD( LEAF )->blk_right_delim_key;
- goto found;
- }
- depth++;
-
- DEBUG_F( " depth=%u, i=%u\n", depth, INFO->next_key_nr[depth] );
-
- }
- while ( INFO->next_key_nr[depth] == 0 );
-
- if ( depth == INFO->tree_depth )
- cache = ROOT;
- else if ( depth <= INFO->cached_slots )
- cache = CACHE( depth );
- else
- {
- cache = read_tree_node( INFO->blocks[depth], --depth );
- if ( !cache )
- return 0;
- }
-
- do
- {
- __u16 nr_item = blkh_nr_item(BLOCKHEAD( cache ));
- int key_nr = INFO->next_key_nr[depth]++;
-
-
- DEBUG_F( " depth=%u, i=%u/%u\n", depth, key_nr, nr_item );
-
- if ( key_nr == nr_item )
- /* This is the last item in this block, set the next_key_nr *
- * to 0 */
- INFO->next_key_nr[depth] = 0;
-
- cache =
- read_tree_node( dc_block_number( &(DC( cache )[key_nr])),
- --depth );
- if ( !cache )
- return 0;
- }
- while ( depth > BLKH_LEVEL_LEAF );
-
- ih = ITEMHEAD;
- }
- found:
- INFO->current_ih = ih;
- INFO->current_item = &LEAF[ih_location(ih)];
-
- DEBUG_F( " new ih: key %u:%u:%u:%u version:%u\n",
- le32_to_cpu(INFO->current_ih->ih_key.k_dir_id),
- le32_to_cpu(INFO->current_ih->ih_key.k_objectid),
- le32_to_cpu(INFO->current_ih->ih_key.u.k_offset_v1.k_offset),
- le32_to_cpu(INFO->current_ih->ih_key.u.k_offset_v1.k_uniqueness),
- ih_version(INFO->current_ih) );
-
- return 1;
+ __u16 depth;
+ struct item_head *ih = INFO->current_ih + 1;
+ char *cache;
+
+
+ DEBUG_F( "next_key:\n old ih: key %u:%u:%u:%u version:%u\n",
+ le32_to_cpu(INFO->current_ih->ih_key.k_dir_id),
+ le32_to_cpu(INFO->current_ih->ih_key.k_objectid),
+ le32_to_cpu(INFO->current_ih->ih_key.u.k_offset_v1.k_offset),
+ le32_to_cpu(INFO->current_ih->ih_key.u.k_offset_v1.k_uniqueness),
+ ih_version(INFO->current_ih) );
+
+
+ if ( ih == &ITEMHEAD[blkh_nr_item(BLOCKHEAD( LEAF ))] )
+ {
+ depth = BLKH_LEVEL_LEAF;
+ /* The last item, was the last in the leaf node. * Read in the next
+ * * block */
+ do
+ {
+ if ( depth == INFO->tree_depth )
+ {
+ /* There are no more keys at all. * Return a dummy item with
+ * * MAX_KEY */
+ ih =
+ ( struct item_head * )
+ &BLOCKHEAD( LEAF )->blk_right_delim_key;
+ goto found;
+ }
+ depth++;
+
+ DEBUG_F( " depth=%u, i=%u\n", depth, INFO->next_key_nr[depth] );
+
+ }
+ while ( INFO->next_key_nr[depth] == 0 );
+
+ if ( depth == INFO->tree_depth )
+ cache = ROOT;
+ else if ( depth <= INFO->cached_slots )
+ cache = CACHE( depth );
+ else
+ {
+ cache = read_tree_node( INFO->blocks[depth], --depth );
+ if ( !cache )
+ return 0;
+ }
+
+ do
+ {
+ __u16 nr_item = blkh_nr_item(BLOCKHEAD( cache ));
+ int key_nr = INFO->next_key_nr[depth]++;
+
+
+ DEBUG_F( " depth=%u, i=%u/%u\n", depth, key_nr, nr_item );
+
+ if ( key_nr == nr_item )
+ /* This is the last item in this block, set the next_key_nr *
+ * to 0 */
+ INFO->next_key_nr[depth] = 0;
+
+ cache =
+ read_tree_node( dc_block_number( &(DC( cache )[key_nr])),
+ --depth );
+ if ( !cache )
+ return 0;
+ }
+ while ( depth > BLKH_LEVEL_LEAF );
+
+ ih = ITEMHEAD;
+ }
+found:
+ INFO->current_ih = ih;
+ INFO->current_item = &LEAF[ih_location(ih)];
+
+ DEBUG_F( " new ih: key %u:%u:%u:%u version:%u\n",
+ le32_to_cpu(INFO->current_ih->ih_key.k_dir_id),
+ le32_to_cpu(INFO->current_ih->ih_key.k_objectid),
+ le32_to_cpu(INFO->current_ih->ih_key.u.k_offset_v1.k_offset),
+ le32_to_cpu(INFO->current_ih->ih_key.u.k_offset_v1.k_uniqueness),
+ ih_version(INFO->current_ih) );
+
+ return 1;
}
/* preconditions: reiserfs_read_super already executed, therefore
static int
search_stat( __u32 dir_id, __u32 objectid )
{
- char *cache;
- int depth;
- int nr_item;
- int i;
- struct item_head *ih;
+ char *cache;
+ int depth;
+ int nr_item;
+ int i;
+ struct item_head *ih;
- DEBUG_F( "search_stat:\n key %u:%u:0:0\n", le32_to_cpu(dir_id),
- le32_to_cpu(objectid) );
+ DEBUG_F( "search_stat:\n key %u:%u:0:0\n", le32_to_cpu(dir_id),
+ le32_to_cpu(objectid) );
- depth = INFO->tree_depth;
- cache = ROOT;
+ depth = INFO->tree_depth;
+ cache = ROOT;
- DEBUG_F( "depth = %d\n", depth );
- while ( depth > BLKH_LEVEL_LEAF )
- {
- struct key *key;
+ DEBUG_F( "depth = %d\n", depth );
+ while ( depth > BLKH_LEVEL_LEAF )
+ {
+ struct key *key;
- nr_item = blkh_nr_item(BLOCKHEAD( cache ));
+ nr_item = blkh_nr_item(BLOCKHEAD( cache ));
- key = KEY( cache );
+ key = KEY( cache );
- for ( i = 0; i < nr_item; i++ )
- {
- if (le32_to_cpu(key->k_dir_id) > le32_to_cpu(dir_id)
- || (key->k_dir_id == dir_id
- && (le32_to_cpu(key->k_objectid) > le32_to_cpu(objectid)
- || (key->k_objectid == objectid
- && (key->u.k_offset_v1.k_offset
- | key->u.k_offset_v1.k_uniqueness) > 0))))
- break;
- key++;
- }
+ for ( i = 0; i < nr_item; i++ )
+ {
+ if (le32_to_cpu(key->k_dir_id) > le32_to_cpu(dir_id)
+ || (key->k_dir_id == dir_id
+ && (le32_to_cpu(key->k_objectid) > le32_to_cpu(objectid)
+ || (key->k_objectid == objectid
+ && (key->u.k_offset_v1.k_offset
+ | key->u.k_offset_v1.k_uniqueness) > 0))))
+ break;
+ key++;
+ }
- DEBUG_F( " depth=%d, i=%d/%d\n", depth, i, nr_item );
+ DEBUG_F( " depth=%d, i=%d/%d\n", depth, i, nr_item );
- INFO->next_key_nr[depth] = ( i == nr_item ) ? 0 : i + 1;
- cache = read_tree_node( dc_block_number(&(DC(cache)[i])), --depth );
- if ( !cache )
- return 0;
- }
+ INFO->next_key_nr[depth] = ( i == nr_item ) ? 0 : i + 1;
+ cache = read_tree_node( dc_block_number(&(DC(cache)[i])), --depth );
+ if ( !cache )
+ return 0;
+ }
- /* cache == LEAF */
- nr_item = blkh_nr_item(BLOCKHEAD(LEAF));
- ih = ITEMHEAD;
- DEBUG_F( "nr_item = %d\n", nr_item );
- for ( i = 0; i < nr_item; i++ )
- {
- if ( ih->ih_key.k_dir_id == dir_id
- && ih->ih_key.k_objectid == objectid
- && ih->ih_key.u.k_offset_v1.k_offset == 0
- && ih->ih_key.u.k_offset_v1.k_uniqueness == 0 )
- {
+ /* cache == LEAF */
+ nr_item = blkh_nr_item(BLOCKHEAD(LEAF));
+ ih = ITEMHEAD;
+ DEBUG_F( "nr_item = %d\n", nr_item );
+ for ( i = 0; i < nr_item; i++ )
+ {
+ if ( ih->ih_key.k_dir_id == dir_id
+ && ih->ih_key.k_objectid == objectid
+ && ih->ih_key.u.k_offset_v1.k_offset == 0
+ && ih->ih_key.u.k_offset_v1.k_uniqueness == 0 )
+ {
- DEBUG_F( " depth=%d, i=%d/%d\n", depth, i, nr_item );
+ DEBUG_F( " depth=%d, i=%d/%d\n", depth, i, nr_item );
- INFO->current_ih = ih;
- INFO->current_item = &LEAF[ih_location(ih)];
+ INFO->current_ih = ih;
+ INFO->current_item = &LEAF[ih_location(ih)];
- return 1;
- }
+ return 1;
+ }
- ih++;
- }
+ ih++;
+ }
- DEBUG_LEAVE(FILE_ERR_BAD_FSYS);
- errnum = FILE_ERR_BAD_FSYS;
- return 0;
+ DEBUG_LEAVE(FILE_ERR_BAD_FSYS);
+ errnum = FILE_ERR_BAD_FSYS;
+ return 0;
}
static int
reiserfs_read_data( char *buf, __u32 len )
{
- __u32 blocksize;
- __u32 offset;
- __u32 to_read;
- char *prev_buf = buf;
+ __u32 blocksize;
+ __u32 offset;
+ __u32 to_read;
+ char *prev_buf = buf;
- DEBUG_F( "reiserfs_read_data: INFO->file->pos=%Lu len=%u, offset=%Lu\n",
- INFO->file->pos, len, (__u64) IH_KEY_OFFSET(INFO->current_ih) - 1 );
+ DEBUG_F( "reiserfs_read_data: INFO->file->pos=%Lu len=%u, offset=%Lu\n",
+ INFO->file->pos, len, (__u64) IH_KEY_OFFSET(INFO->current_ih) - 1 );
- if ( INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid
- || IH_KEY_OFFSET( INFO->current_ih ) > INFO->file->pos + 1 )
- {
- search_stat( INFO->fileinfo.k_dir_id, INFO->fileinfo.k_objectid );
- goto get_next_key;
- }
+ if ( INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid
+ || IH_KEY_OFFSET( INFO->current_ih ) > INFO->file->pos + 1 )
+ {
+ search_stat( INFO->fileinfo.k_dir_id, INFO->fileinfo.k_objectid );
+ goto get_next_key;
+ }
- while ( errnum == 0 )
- {
- if ( INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid )
- break;
+ while ( errnum == 0 )
+ {
+ if ( INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid )
+ break;
- offset = INFO->file->pos - IH_KEY_OFFSET( INFO->current_ih ) + 1;
- blocksize = ih_item_len(INFO->current_ih);
+ offset = INFO->file->pos - IH_KEY_OFFSET( INFO->current_ih ) + 1;
+ blocksize = ih_item_len(INFO->current_ih);
- DEBUG_F( " loop: INFO->file->pos=%Lu len=%u, offset=%u blocksize=%u\n",
- INFO->file->pos, len, offset, blocksize );
+ DEBUG_F( " loop: INFO->file->pos=%Lu len=%u, offset=%u blocksize=%u\n",
+ INFO->file->pos, len, offset, blocksize );
- if ( IH_KEY_ISTYPE( INFO->current_ih, TYPE_DIRECT )
- && offset < blocksize )
- {
- to_read = blocksize - offset;
- if ( to_read > len )
- to_read = len;
-
- memcpy( buf, INFO->current_item + offset, to_read );
- goto update_buf_len;
- }
- else if ( IH_KEY_ISTYPE( INFO->current_ih, TYPE_INDIRECT ) )
- {
- blocksize = ( blocksize >> 2 ) << INFO->blocksize_shift;
-
- while ( offset < blocksize )
- {
- __u32 blocknr = le32_to_cpu(((__u32 *)
- INFO->current_item)[offset >> INFO->blocksize_shift]);
-
- int blk_offset = offset & (INFO->blocksize - 1);
-
- to_read = INFO->blocksize - blk_offset;
- if ( to_read > len )
+ if ( IH_KEY_ISTYPE( INFO->current_ih, TYPE_DIRECT )
+ && offset < blocksize )
+ {
+ to_read = blocksize - offset;
+ if ( to_read > len )
to_read = len;
- /* Journal is only for meta data.
- Data blocks can be read directly without using block_read */
- read_disk_block( INFO->file, blocknr, blk_offset, to_read,
- buf );
-
- update_buf_len:
- len -= to_read;
- buf += to_read;
- offset += to_read;
- INFO->file->pos += to_read;
- if ( len == 0 )
- goto done;
- }
- }
- get_next_key:
- next_key();
- }
- done:
- return (errnum != 0) ? 0 : buf - prev_buf;
+ memcpy( buf, INFO->current_item + offset, to_read );
+ goto update_buf_len;
+ }
+ else if ( IH_KEY_ISTYPE( INFO->current_ih, TYPE_INDIRECT ) )
+ {
+ blocksize = ( blocksize >> 2 ) << INFO->blocksize_shift;
+
+ while ( offset < blocksize )
+ {
+ __u32 blocknr = le32_to_cpu(((__u32 *)
+ INFO->current_item)[offset >> INFO->blocksize_shift]);
+
+ int blk_offset = offset & (INFO->blocksize - 1);
+
+ to_read = INFO->blocksize - blk_offset;
+ if ( to_read > len )
+ to_read = len;
+
+ /* Journal is only for meta data.
+ Data blocks can be read directly without using block_read */
+ read_disk_block( INFO->file, blocknr, blk_offset, to_read,
+ buf );
+
+ update_buf_len:
+ len -= to_read;
+ buf += to_read;
+ offset += to_read;
+ INFO->file->pos += to_read;
+ if ( len == 0 )
+ goto done;
+ }
+ }
+ get_next_key:
+ next_key();
+ }
+done:
+ return (errnum != 0) ? 0 : buf - prev_buf;
}
static int
reiserfs_open_file( char *dirname )
{
- struct reiserfs_de_head *de_head;
- char *rest, ch;
- __u32 dir_id, objectid, parent_dir_id = 0, parent_objectid = 0;
+ struct reiserfs_de_head *de_head;
+ char *rest, ch;
+ __u32 dir_id, objectid, parent_dir_id = 0, parent_objectid = 0;
+
+ char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
+ int link_count = 0;
+ int mode;
- char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
- int link_count = 0;
- int mode;
-
- dir_id = cpu_to_le32(REISERFS_ROOT_PARENT_OBJECTID);
- objectid = cpu_to_le32(REISERFS_ROOT_OBJECTID);
-
- while ( 1 )
- {
-
- DEBUG_F( "dirname=%s\n", dirname );
-
- /* Search for the stat info first. */
- if ( !search_stat( dir_id, objectid ) )
- return 0;
-
-
- DEBUG_F( "sd_mode=0%o sd_size=%u\n",
- sd_mode((struct stat_data *) INFO->current_item ),
- sd_size(INFO->current_ih, INFO->current_item ));
-
-
- mode = sd_mode((struct stat_data *)INFO->current_item);
-
- /* If we've got a symbolic link, then chase it. */
- if ( S_ISLNK( mode ) )
- {
- int len = 0;
-
- if ( ++link_count > MAX_LINK_COUNT )
- {
- errnum = FILE_ERR_SYMLINK_LOOP;
- return 0;
- }
-
- /* Get the symlink size. */
- INFO->file->len = sd_size(INFO->current_ih, INFO->current_item);
-
- /* Find out how long our remaining name is. */
- while ( dirname[len] && !isspace( dirname[len] ) )
- len++;
-
- if ( INFO->file->len + len > sizeof ( linkbuf ) - 1 )
- {
- errnum = FILE_ERR_LENGTH;
- return 0;
- }
-
- /* Copy the remaining name to the end of the symlink data. Note *
- * that DIRNAME and LINKBUF may overlap! */
- memmove( linkbuf + INFO->file->len, dirname, len + 1 );
-
- INFO->fileinfo.k_dir_id = dir_id;
- INFO->fileinfo.k_objectid = objectid;
- INFO->file->pos = 0;
- if ( !next_key()
- || reiserfs_read_data( linkbuf, INFO->file->len ) != INFO->file->len )
- return 0;
-
-
- DEBUG_F( "symlink=%s\n", linkbuf );
-
-
- dirname = linkbuf;
- if ( *dirname == '/' )
- {
- /* It's an absolute link, so look it up in root. */
- dir_id = cpu_to_le32(REISERFS_ROOT_PARENT_OBJECTID);
- objectid = cpu_to_le32(REISERFS_ROOT_OBJECTID);
- }
- else
- {
- /* Relative, so look it up in our parent directory. */
- dir_id = parent_dir_id;
- objectid = parent_objectid;
- }
-
- /* Now lookup the new name. */
- continue;
- }
-
- /* if we have a real file (and we're not just printing *
- * possibilities), then this is where we want to exit */
-
- if ( !*dirname || isspace( *dirname ) )
- {
- if ( !S_ISREG( mode ) )
- {
- errnum = FILE_ERR_BAD_TYPE;
- return 0;
- }
-
- INFO->file->pos = 0;
- INFO->file->len = sd_size(INFO->current_ih, INFO->current_item);
-
- INFO->fileinfo.k_dir_id = dir_id;
- INFO->fileinfo.k_objectid = objectid;
- return next_key();
- }
-
- /* continue with the file/directory name interpretation */
- while ( *dirname == '/' )
- dirname++;
- if ( !S_ISDIR( mode ) )
- {
- errnum = FILE_ERR_BAD_TYPE;
- return 0;
- }
- for ( rest = dirname; ( ch = *rest ) && !isspace( ch ) && ch != '/';
- rest++ ) ;
- *rest = 0;
-
- while ( 1 )
- {
- char *name_end;
- int num_entries;
-
- if ( !next_key() )
- return 0;
-
- if ( INFO->current_ih->ih_key.k_objectid != objectid )
- break;
-
- name_end = INFO->current_item + ih_item_len(INFO->current_ih);
- de_head = ( struct reiserfs_de_head * ) INFO->current_item;
- num_entries = ih_entry_count(INFO->current_ih);
- while ( num_entries > 0 )
- {
- char *filename = INFO->current_item + deh_location(de_head);
- char tmp = *name_end;
-
- if( deh_state(de_head) & (1 << DEH_Visible))
- {
- int cmp;
-
- /* Directory names in ReiserFS are not null * terminated.
- * We write a temporary 0 behind it. * NOTE: that this
- * may overwrite the first block in * the tree cache.
- * That doesn't hurt as long as we * don't call next_key
- * () in between. */
- *name_end = 0;
- cmp = strcmp( dirname, filename );
- *name_end = tmp;
- if ( cmp == 0 )
- goto found;
- }
- /* The beginning of this name marks the end of the next name.
- */
- name_end = filename;
- de_head++;
- num_entries--;
- }
- }
-
- errnum = FILE_ERR_NOTFOUND;
- *rest = ch;
- return 0;
-
- found:
- *rest = ch;
- dirname = rest;
-
- parent_dir_id = dir_id;
- parent_objectid = objectid;
- dir_id = de_head->deh_dir_id; /* LE */
- objectid = de_head->deh_objectid; /* LE */
- }
+ dir_id = cpu_to_le32(REISERFS_ROOT_PARENT_OBJECTID);
+ objectid = cpu_to_le32(REISERFS_ROOT_OBJECTID);
+
+ while ( 1 )
+ {
+
+ DEBUG_F( "dirname=%s\n", dirname );
+
+ /* Search for the stat info first. */
+ if ( !search_stat( dir_id, objectid ) )
+ return 0;
+
+
+ DEBUG_F( "sd_mode=0%o sd_size=%Lu\n",
+ sd_mode((struct stat_data *) INFO->current_item ),
+ sd_size(INFO->current_ih, INFO->current_item ));
+
+
+ mode = sd_mode((struct stat_data *)INFO->current_item);
+
+ /* If we've got a symbolic link, then chase it. */
+ if ( S_ISLNK( mode ) )
+ {
+ int len = 0;
+
+ DEBUG_F("link count = %d\n", link_count);
+ DEBUG_SLEEP;
+ if ( ++link_count > MAX_LINK_COUNT )
+ {
+ DEBUG_F("Symlink loop\n");
+ errnum = FILE_ERR_SYMLINK_LOOP;
+ return 0;
+ }
+
+ /* Get the symlink size. */
+ INFO->file->len = sd_size(INFO->current_ih, INFO->current_item);
+
+ /* Find out how long our remaining name is. */
+ while ( dirname[len] && !isspace( dirname[len] ) )
+ len++;
+
+ if ( INFO->file->len + len > sizeof ( linkbuf ) - 1 )
+ {
+ errnum = FILE_ERR_LENGTH;
+ return 0;
+ }
+
+ /* Copy the remaining name to the end of the symlink data. Note *
+ * that DIRNAME and LINKBUF may overlap! */
+ memmove( linkbuf + INFO->file->len, dirname, len + 1 );
+
+ INFO->fileinfo.k_dir_id = dir_id;
+ INFO->fileinfo.k_objectid = objectid;
+ INFO->file->pos = 0;
+ if ( !next_key()
+ || reiserfs_read_data( linkbuf, INFO->file->len ) != INFO->file->len ) {
+ DEBUG_F("reiserfs_open_file - if !next_key || reiserfs_read_data\n");
+ DEBUG_SLEEP;
+ errnum = FILE_IOERR;
+ return 0;
+ }
+
+
+ DEBUG_F( "symlink=%s\n", linkbuf );
+ DEBUG_SLEEP;
+
+ dirname = linkbuf;
+ if ( *dirname == '/' )
+ {
+ /* It's an absolute link, so look it up in root. */
+ dir_id = cpu_to_le32(REISERFS_ROOT_PARENT_OBJECTID);
+ objectid = cpu_to_le32(REISERFS_ROOT_OBJECTID);
+ }
+ else
+ {
+ /* Relative, so look it up in our parent directory. */
+ dir_id = parent_dir_id;
+ objectid = parent_objectid;
+ }
+
+ /* Now lookup the new name. */
+ continue;
+ }
+
+ /* if we have a real file (and we're not just printing *
+ * possibilities), then this is where we want to exit */
+
+ if ( !*dirname || isspace( *dirname ) )
+ {
+ if ( !S_ISREG( mode ) )
+ {
+ errnum = FILE_ERR_BAD_TYPE;
+ return 0;
+ }
+
+ INFO->file->pos = 0;
+ INFO->file->len = sd_size(INFO->current_ih, INFO->current_item);
+
+ INFO->fileinfo.k_dir_id = dir_id;
+ INFO->fileinfo.k_objectid = objectid;
+ return next_key();
+ }
+
+ /* continue with the file/directory name interpretation */
+ while ( *dirname == '/' )
+ dirname++;
+ if ( !S_ISDIR( mode ) )
+ {
+ errnum = FILE_ERR_NOTDIR;
+ return 0;
+ }
+ for ( rest = dirname; ( ch = *rest ) && !isspace( ch ) && ch != '/';
+ rest++ ) ;
+ *rest = 0;
+
+ while ( 1 )
+ {
+ char *name_end;
+ int num_entries;
+
+ if ( !next_key() )
+ return 0;
+
+ if ( INFO->current_ih->ih_key.k_objectid != objectid )
+ break;
+
+ name_end = INFO->current_item + ih_item_len(INFO->current_ih);
+ de_head = ( struct reiserfs_de_head * ) INFO->current_item;
+ num_entries = ih_entry_count(INFO->current_ih);
+ while ( num_entries > 0 )
+ {
+ char *filename = INFO->current_item + deh_location(de_head);
+ char tmp = *name_end;
+
+ if( deh_state(de_head) & (1 << DEH_Visible))
+ {
+ int cmp;
+
+ /* Directory names in ReiserFS are not null * terminated.
+ * We write a temporary 0 behind it. * NOTE: that this
+ * may overwrite the first block in * the tree cache.
+ * That doesn't hurt as long as we * don't call next_key
+ * () in between. */
+ *name_end = 0;
+ cmp = strcmp( dirname, filename );
+ *name_end = tmp;
+ if ( cmp == 0 )
+ goto found;
+ }
+ /* The beginning of this name marks the end of the next name.
+ */
+ name_end = filename;
+ de_head++;
+ num_entries--;
+ }
+ }
+
+ errnum = FILE_ERR_NOTFOUND;
+ *rest = ch;
+ return 0;
+
+ found:
+ *rest = ch;
+ dirname = rest;
+
+ parent_dir_id = dir_id;
+ parent_objectid = objectid;
+ dir_id = de_head->deh_dir_id; /* LE */
+ objectid = de_head->deh_objectid; /* LE */
+ }
}
#ifndef __LITTLE_ENDIAN
typedef union {
- struct offset_v2 offset_v2;
- __u64 linear;
+ struct offset_v2 offset_v2;
+ __u64 linear;
} offset_v2_esafe_overlay;
inline __u16
offset_v2_k_type( struct offset_v2 *v2 )
{
- offset_v2_esafe_overlay tmp = *(offset_v2_esafe_overlay *)v2;
- tmp.linear = le64_to_cpu( tmp.linear );
- return tmp.offset_v2.k_type;
+ offset_v2_esafe_overlay tmp = *(offset_v2_esafe_overlay *)v2;
+ tmp.linear = le64_to_cpu( tmp.linear );
+ return tmp.offset_v2.k_type;
}
inline loff_t
offset_v2_k_offset( struct offset_v2 *v2 )
{
- offset_v2_esafe_overlay tmp = *(offset_v2_esafe_overlay *)v2;
- tmp.linear = le64_to_cpu( tmp.linear );
- return tmp.offset_v2.k_offset;
+ offset_v2_esafe_overlay tmp = *(offset_v2_esafe_overlay *)v2;
+ tmp.linear = le64_to_cpu( tmp.linear );
+ return tmp.offset_v2.k_offset;
}
#endif
inline int
uniqueness2type (__u32 uniqueness)
{
- switch (uniqueness) {
- case V1_SD_UNIQUENESS: return TYPE_STAT_DATA;
- case V1_INDIRECT_UNIQUENESS: return TYPE_INDIRECT;
- case V1_DIRECT_UNIQUENESS: return TYPE_DIRECT;
- case V1_DIRENTRY_UNIQUENESS: return TYPE_DIRENTRY;
- }
- return TYPE_ANY;
+ switch (uniqueness) {
+ case V1_SD_UNIQUENESS: return TYPE_STAT_DATA;
+ case V1_INDIRECT_UNIQUENESS: return TYPE_INDIRECT;
+ case V1_DIRECT_UNIQUENESS: return TYPE_DIRECT;
+ case V1_DIRENTRY_UNIQUENESS: return TYPE_DIRENTRY;
+ }
+ return TYPE_ANY;
}
+
+/*
+ * Local variables:
+ * c-file-style: "K&R"
+ * c-basic-offset: 5
+ * End:
+ */
--- /dev/null
+/*
+ * fsys_xfs.c - an implementation for the SGI XFS file system
+ *
+ * Copyright (C) 2001 Ethan Benson
+ *
+ * Adapted from Grub
+ *
+ * Copyright (C) 2001 Serguei Tzukanov
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "types.h"
+#include "ctype.h"
+#include "string.h"
+#include "stdlib.h"
+#include "fs.h"
+#include "xfs/xfs.h"
+#include "errors.h"
+
+#define SECTOR_BITS 9
+
+int xfs_mount (void);
+int xfs_read_data (char *buf, int len);
+int xfs_dir (char *dirname);
+
+/* Exported in struct fs_t */
+static int xfs_open(struct boot_file_t *file, const char *dev_name,
+ struct partition_t *part, const char *file_name);
+static int xfs_read(struct boot_file_t *file, unsigned int size, void *buffer);
+static int xfs_seek(struct boot_file_t *file, unsigned int newpos);
+static int xfs_close(struct boot_file_t *file);
+
+struct fs_t xfs_filesystem = {
+ name:"xfs",
+ open:xfs_open,
+ read:xfs_read,
+ seek:xfs_seek,
+ close:xfs_close
+};
+
+struct boot_file_t *xfs_file;
+static char FSYS_BUF[32768];
+__u64 partition_offset;
+int errnum;
+
+static int
+xfs_open(struct boot_file_t *file, const char *dev_name,
+ struct partition_t *part, const char *file_name)
+{
+ static char buffer[1024];
+
+ DEBUG_ENTER;
+ DEBUG_OPEN;
+
+ if (part)
+ {
+ DEBUG_F("Determining offset for partition %d\n", part->part_number);
+ partition_offset = ((__u64)(part->part_start)) * ((__u64)part->blocksize);
+ DEBUG_F("%Lu = %lu * %hu\n", partition_offset,
+ part->part_start,
+ part->blocksize);
+ }
+ else
+ partition_offset = 0;
+
+ sprintf(buffer, "%s:%d", dev_name, 0); /* 0 is full disk in OF */
+ DEBUG_F("Trying to open dev_name=%s; filename=%s; partition offset=%Lu\n",
+ buffer, file_name, partition_offset);
+ file->of_device = prom_open(buffer);
+
+ if (file->of_device == PROM_INVALID_HANDLE || file->of_device == NULL)
+ {
+ DEBUG_F("Can't open device %p\n", file->of_device);
+ DEBUG_LEAVE(FILE_ERR_BADDEV);
+ return FILE_ERR_BADDEV;
+ }
+
+ DEBUG_F("%p was successfully opened\n", file->of_device);
+
+ xfs_file = file;
+
+ if (xfs_mount() != 1)
+ {
+ DEBUG_F("Couldn't open XFS @ %s/%Lu\n", buffer, partition_offset);
+ prom_close(file->of_device);
+ DEBUG_LEAVE(FILE_ERR_BAD_FSYS);
+ DEBUG_SLEEP;
+ return FILE_ERR_BAD_FSYS;
+ }
+
+ DEBUG_F("Attempting to open %s\n", file_name);
+ strcpy(buffer, file_name); /* xfs_dir modifies argument */
+ if(!xfs_dir(buffer))
+ {
+ DEBUG_F("xfs_dir() failed. errnum = %d\n", errnum);
+ prom_close( file->of_device );
+ DEBUG_LEAVE_F(errnum);
+ DEBUG_SLEEP;
+ return errnum;
+ }
+
+ DEBUG_F("Successfully opened %s\n", file_name);
+
+ DEBUG_LEAVE(FILE_ERR_OK);
+ return FILE_ERR_OK;
+}
+
+static int
+xfs_read(struct boot_file_t *file, unsigned int size, void *buffer)
+{
+ return xfs_read_data(buffer, size);
+}
+
+static int
+xfs_seek(struct boot_file_t *file, unsigned int newpos)
+{
+ file->pos = newpos;
+ return FILE_ERR_OK;
+}
+
+static int
+xfs_close(struct boot_file_t *file)
+{
+ if(file->of_device)
+ {
+ prom_close(file->of_device);
+ file->of_device = 0;
+ DEBUG_F("xfs_close called\n");
+ }
+ return FILE_ERR_OK;
+}
+
+static int
+read_disk_block(struct boot_file_t *file, __u32 block, __u32 start,
+ __u32 length, void *buf)
+{
+ unsigned long long pos = block * 512;
+ pos += partition_offset + start;
+ DEBUG_F("Reading %u bytes, starting at block %u, disk offset %Lu\n",
+ length, block, pos);
+ if (!prom_lseek(file->of_device, pos)) {
+ DEBUG_F("prom_lseek failed\n");
+ return 0;
+ }
+ return prom_read(file->of_device, buf, length);
+}
+
+#define MAX_LINK_COUNT 8
+
+typedef struct xad {
+ xfs_fileoff_t offset;
+ xfs_fsblock_t start;
+ xfs_filblks_t len;
+} xad_t;
+
+struct xfs_info {
+ int bsize;
+ int dirbsize;
+ int isize;
+ unsigned int agblocks;
+ int bdlog;
+ int blklog;
+ int inopblog;
+ int agblklog;
+ int agnolog;
+ int dirblklog;
+ unsigned int nextents;
+ xfs_daddr_t next;
+ xfs_daddr_t daddr;
+ xfs_dablk_t forw;
+ xfs_dablk_t dablk;
+ xfs_bmbt_rec_32_t *xt;
+ xfs_bmbt_ptr_t ptr0;
+ int btnode_ptr0_off;
+ int i8param;
+ int dirpos;
+ int dirmax;
+ int blkoff;
+ int fpos;
+ xfs_ino_t rootino;
+};
+
+static struct xfs_info xfs;
+
+#define dirbuf ((char *)FSYS_BUF)
+#define filebuf ((char *)FSYS_BUF + 4096)
+#define inode ((xfs_dinode_t *)((char *)FSYS_BUF + 8192))
+#define icore (inode->di_core)
+
+#define mask32lo(n) (((__uint32_t)1 << (n)) - 1)
+
+#define XFS_INO_MASK(k) ((__uint32_t)((1ULL << (k)) - 1))
+#define XFS_INO_OFFSET_BITS xfs.inopblog
+#define XFS_INO_AGBNO_BITS xfs.agblklog
+#define XFS_INO_AGINO_BITS (xfs.agblklog + xfs.inopblog)
+#define XFS_INO_AGNO_BITS xfs.agnolog
+
+static inline xfs_agblock_t
+agino2agbno (xfs_agino_t agino)
+{
+ return agino >> XFS_INO_OFFSET_BITS;
+}
+
+static inline xfs_agnumber_t
+ino2agno (xfs_ino_t ino)
+{
+ return ino >> XFS_INO_AGINO_BITS;
+}
+
+static inline xfs_agino_t
+ino2agino (xfs_ino_t ino)
+{
+ return ino & XFS_INO_MASK(XFS_INO_AGINO_BITS);
+}
+
+static inline int
+ino2offset (xfs_ino_t ino)
+{
+ return ino & XFS_INO_MASK(XFS_INO_OFFSET_BITS);
+}
+
+/* XFS is big endian, powerpc is big endian */
+
+static inline __const__ __uint16_t
+le16 (__uint16_t x)
+{
+ return x;
+}
+
+static inline __const__ __uint32_t
+le32 (__uint32_t x)
+{
+ return x;
+}
+
+static inline __const__ __uint64_t
+le64 (__uint64_t x)
+{
+ return x;
+}
+
+static xfs_fsblock_t
+xt_start (xfs_bmbt_rec_32_t *r)
+{
+ return (((xfs_fsblock_t)(le32 (r->l1) & mask32lo(9))) << 43) |
+ (((xfs_fsblock_t)le32 (r->l2)) << 11) |
+ (((xfs_fsblock_t)le32 (r->l3)) >> 21);
+}
+
+static xfs_fileoff_t
+xt_offset (xfs_bmbt_rec_32_t *r)
+{
+ return (((xfs_fileoff_t)le32 (r->l0) &
+ mask32lo(31)) << 23) |
+ (((xfs_fileoff_t)le32 (r->l1)) >> 9);
+}
+
+static xfs_filblks_t
+xt_len (xfs_bmbt_rec_32_t *r)
+{
+ return le32(r->l3) & mask32lo(21);
+}
+
+static const char xfs_highbit[256] = {
+ -1, 0, 1, 1, 2, 2, 2, 2, /* 00 .. 07 */
+ 3, 3, 3, 3, 3, 3, 3, 3, /* 08 .. 0f */
+ 4, 4, 4, 4, 4, 4, 4, 4, /* 10 .. 17 */
+ 4, 4, 4, 4, 4, 4, 4, 4, /* 18 .. 1f */
+ 5, 5, 5, 5, 5, 5, 5, 5, /* 20 .. 27 */
+ 5, 5, 5, 5, 5, 5, 5, 5, /* 28 .. 2f */
+ 5, 5, 5, 5, 5, 5, 5, 5, /* 30 .. 37 */
+ 5, 5, 5, 5, 5, 5, 5, 5, /* 38 .. 3f */
+ 6, 6, 6, 6, 6, 6, 6, 6, /* 40 .. 47 */
+ 6, 6, 6, 6, 6, 6, 6, 6, /* 48 .. 4f */
+ 6, 6, 6, 6, 6, 6, 6, 6, /* 50 .. 57 */
+ 6, 6, 6, 6, 6, 6, 6, 6, /* 58 .. 5f */
+ 6, 6, 6, 6, 6, 6, 6, 6, /* 60 .. 67 */
+ 6, 6, 6, 6, 6, 6, 6, 6, /* 68 .. 6f */
+ 6, 6, 6, 6, 6, 6, 6, 6, /* 70 .. 77 */
+ 6, 6, 6, 6, 6, 6, 6, 6, /* 78 .. 7f */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 80 .. 87 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 88 .. 8f */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 90 .. 97 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 98 .. 9f */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* a0 .. a7 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* a8 .. af */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* b0 .. b7 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* b8 .. bf */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* c0 .. c7 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* c8 .. cf */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* d0 .. d7 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* d8 .. df */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* e0 .. e7 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* e8 .. ef */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* f0 .. f7 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* f8 .. ff */
+};
+
+static int
+xfs_highbit32(__uint32_t v)
+{
+ int i;
+
+ if (v & 0xffff0000)
+ if (v & 0xff000000)
+ i = 24;
+ else
+ i = 16;
+ else if (v & 0x0000ffff)
+ if (v & 0x0000ff00)
+ i = 8;
+ else
+ i = 0;
+ else
+ return -1;
+ return i + xfs_highbit[(v >> i) & 0xff];
+}
+
+static int
+isinxt (xfs_fileoff_t key, xfs_fileoff_t offset, xfs_filblks_t len)
+{
+ return (key >= offset) ? (key < offset + len ? 1 : 0) : 0;
+}
+
+static xfs_daddr_t
+agb2daddr (xfs_agnumber_t agno, xfs_agblock_t agbno)
+{
+ return ((xfs_fsblock_t)agno*xfs.agblocks + agbno) << xfs.bdlog;
+}
+
+static xfs_daddr_t
+fsb2daddr (xfs_fsblock_t fsbno)
+{
+ return agb2daddr ((xfs_agnumber_t)(fsbno >> xfs.agblklog),
+ (xfs_agblock_t)(fsbno & mask32lo(xfs.agblklog)));
+}
+
+static inline int
+btroot_maxrecs (void)
+{
+ int tmp = icore.di_forkoff ? (icore.di_forkoff << 3) : xfs.isize;
+
+ return (tmp - sizeof(xfs_bmdr_block_t) -
+ (int)((char *)&inode->di_u - (char*)inode)) /
+ (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t));
+}
+
+static int
+di_read (xfs_ino_t ino)
+{
+ xfs_agino_t agino;
+ xfs_agnumber_t agno;
+ xfs_agblock_t agbno;
+ xfs_daddr_t daddr;
+ int offset;
+
+ agno = ino2agno (ino);
+ agino = ino2agino (ino);
+ agbno = agino2agbno (agino);
+ offset = ino2offset (ino);
+ daddr = agb2daddr (agno, agbno);
+
+ read_disk_block(xfs_file, daddr, offset*xfs.isize, xfs.isize, (char *)inode);
+
+ xfs.ptr0 = *(xfs_bmbt_ptr_t *)
+ (inode->di_u.di_c + sizeof(xfs_bmdr_block_t)
+ + btroot_maxrecs ()*sizeof(xfs_bmbt_key_t));
+
+ return 1;
+}
+
+static void
+init_extents (void)
+{
+ xfs_bmbt_ptr_t ptr0;
+ xfs_btree_lblock_t h;
+
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_EXTENTS:
+ xfs.xt = inode->di_u.di_bmx;
+ xfs.nextents = le32 (icore.di_nextents);
+ break;
+ case XFS_DINODE_FMT_BTREE:
+ ptr0 = xfs.ptr0;
+ for (;;) {
+ xfs.daddr = fsb2daddr (le64(ptr0));
+ read_disk_block(xfs_file, xfs.daddr, 0,
+ sizeof(xfs_btree_lblock_t), (char *)&h);
+ if (!h.bb_level) {
+ xfs.nextents = le16(h.bb_numrecs);
+ xfs.next = fsb2daddr (le64(h.bb_leftsib));
+ xfs.fpos = sizeof(xfs_btree_block_t);
+ return;
+ }
+ read_disk_block(xfs_file, xfs.daddr, xfs.btnode_ptr0_off,
+ sizeof(xfs_bmbt_ptr_t), (char *)&ptr0);
+ }
+ }
+}
+
+static xad_t *
+next_extent (void)
+{
+ static xad_t xad;
+
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_EXTENTS:
+ if (xfs.nextents == 0)
+ return NULL;
+ break;
+ case XFS_DINODE_FMT_BTREE:
+ if (xfs.nextents == 0) {
+ xfs_btree_lblock_t h;
+ if (xfs.next == 0)
+ return NULL;
+ xfs.daddr = xfs.next;
+ read_disk_block(xfs_file, xfs.daddr, 0,
+ sizeof(xfs_btree_lblock_t), (char *)&h);
+ xfs.nextents = le16(h.bb_numrecs);
+ xfs.next = fsb2daddr (le64(h.bb_leftsib));
+ xfs.fpos = sizeof(xfs_btree_block_t);
+ }
+ /* Yeah, I know that's slow, but I really don't care */
+ read_disk_block(xfs_file, xfs.daddr, xfs.fpos,
+ sizeof(xfs_bmbt_rec_t), filebuf);
+ xfs.xt = (xfs_bmbt_rec_32_t *)filebuf;
+ xfs.fpos += sizeof(xfs_bmbt_rec_32_t);
+ break;
+ default:
+ return NULL;
+ }
+ xad.offset = xt_offset (xfs.xt);
+ xad.start = xt_start (xfs.xt);
+ xad.len = xt_len (xfs.xt);
+ ++xfs.xt;
+ --xfs.nextents;
+
+ return &xad;
+}
+
+/*
+ * Name lies - the function reads only first 100 bytes
+ */
+static void
+xfs_dabread (void)
+{
+ xad_t *xad;
+ xfs_fileoff_t offset;;
+
+ init_extents ();
+ while ((xad = next_extent ())) {
+ offset = xad->offset;
+ if (isinxt (xfs.dablk, offset, xad->len)) {
+ read_disk_block(xfs_file, fsb2daddr (xad->start + xfs.dablk - offset),
+ 0, 100, dirbuf);
+ break;
+ }
+ }
+}
+
+static inline xfs_ino_t
+sf_ino (char *sfe, int namelen)
+{
+ void *p = sfe + namelen + 3;
+
+ return (xfs.i8param == 0)
+ ? le64(*(xfs_ino_t *)p) : le32(*(__uint32_t *)p);
+}
+
+static inline xfs_ino_t
+sf_parent_ino (void)
+{
+ return (xfs.i8param == 0)
+ ? le64(*(xfs_ino_t *)(&inode->di_u.di_dir2sf.hdr.parent))
+ : le32(*(__uint32_t *)(&inode->di_u.di_dir2sf.hdr.parent));
+}
+
+static inline int
+roundup8 (int n)
+{
+ return ((n+7)&~7);
+}
+
+static char *
+next_dentry (xfs_ino_t *ino)
+{
+ int namelen = 1;
+ int toread;
+ static char *usual[2] = {".", ".."};
+ static xfs_dir2_sf_entry_t *sfe;
+ char *name = usual[0];
+
+ if (xfs.dirpos >= xfs.dirmax) {
+ if (xfs.forw == 0)
+ return NULL;
+ xfs.dablk = xfs.forw;
+ xfs_dabread ();
+#define h ((xfs_dir2_leaf_hdr_t *)dirbuf)
+ xfs.dirmax = le16 (h->count) - le16 (h->stale);
+ xfs.forw = le32 (h->info.forw);
+#undef h
+ xfs.dirpos = 0;
+ }
+
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_LOCAL:
+ switch (xfs.dirpos) {
+ case -2:
+ *ino = 0;
+ break;
+ case -1:
+ *ino = sf_parent_ino ();
+ ++name;
+ ++namelen;
+ sfe = (xfs_dir2_sf_entry_t *)
+ (inode->di_u.di_c
+ + sizeof(xfs_dir2_sf_hdr_t)
+ - xfs.i8param);
+ break;
+ default:
+ namelen = sfe->namelen;
+ *ino = sf_ino ((char *)sfe, namelen);
+ name = sfe->name;
+ sfe = (xfs_dir2_sf_entry_t *)
+ ((char *)sfe + namelen + 11 - xfs.i8param);
+ }
+ break;
+ case XFS_DINODE_FMT_BTREE:
+ case XFS_DINODE_FMT_EXTENTS:
+#define dau ((xfs_dir2_data_union_t *)dirbuf)
+ for (;;) {
+ if (xfs.blkoff >= xfs.dirbsize) {
+ xfs.blkoff = sizeof(xfs_dir2_data_hdr_t);
+ xfs_file->pos &= ~(xfs.dirbsize - 1);
+ xfs_file->pos |= xfs.blkoff;
+ }
+ xfs_read_data (dirbuf, 4);
+ xfs.blkoff += 4;
+ if (dau->unused.freetag == XFS_DIR2_DATA_FREE_TAG) {
+ toread = roundup8 (le16(dau->unused.length)) - 4;
+ xfs.blkoff += toread;
+ xfs_file->pos += toread;
+ continue;
+ }
+ break;
+ }
+ xfs_read_data ((char *)dirbuf + 4, 5);
+ *ino = le64 (dau->entry.inumber);
+ namelen = dau->entry.namelen;
+#undef dau
+ toread = roundup8 (namelen + 11) - 9;
+ xfs_read_data (dirbuf, toread);
+ name = (char *)dirbuf;
+ xfs.blkoff += toread + 5;
+ break;
+ }
+ ++xfs.dirpos;
+ name[namelen] = 0;
+
+ return name;
+}
+
+static char *
+first_dentry (xfs_ino_t *ino)
+{
+ xfs.forw = 0;
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_LOCAL:
+ xfs.dirmax = inode->di_u.di_dir2sf.hdr.count;
+ xfs.i8param = inode->di_u.di_dir2sf.hdr.i8count ? 0 : 4;
+ xfs.dirpos = -2;
+ break;
+ case XFS_DINODE_FMT_EXTENTS:
+ case XFS_DINODE_FMT_BTREE:
+ xfs_file->pos = 0;
+ xfs_file->len = le64 (icore.di_size);
+ xfs_read_data (dirbuf, sizeof(xfs_dir2_data_hdr_t));
+ if (((xfs_dir2_data_hdr_t *)dirbuf)->magic == le32(XFS_DIR2_BLOCK_MAGIC)) {
+#define tail ((xfs_dir2_block_tail_t *)dirbuf)
+ xfs_file->pos = xfs.dirbsize - sizeof(*tail);
+ xfs_read_data (dirbuf, sizeof(*tail));
+ xfs.dirmax = le32 (tail->count) - le32 (tail->stale);
+#undef tail
+ } else {
+ xfs.dablk = (1ULL << 35) >> xfs.blklog;
+#define h ((xfs_dir2_leaf_hdr_t *)dirbuf)
+#define n ((xfs_da_intnode_t *)dirbuf)
+ for (;;) {
+ xfs_dabread ();
+ if ((n->hdr.info.magic == le16(XFS_DIR2_LEAFN_MAGIC))
+ || (n->hdr.info.magic == le16(XFS_DIR2_LEAF1_MAGIC))) {
+ xfs.dirmax = le16 (h->count) - le16 (h->stale);
+ xfs.forw = le32 (h->info.forw);
+ break;
+ }
+ xfs.dablk = le32 (n->btree[0].before);
+ }
+#undef n
+#undef h
+ }
+ xfs.blkoff = sizeof(xfs_dir2_data_hdr_t);
+ xfs_file->pos = xfs.blkoff;
+ xfs.dirpos = 0;
+ break;
+ }
+ return next_dentry (ino);
+}
+
+int
+xfs_mount (void)
+{
+ xfs_sb_t super;
+
+ if (read_disk_block(xfs_file, 0, 0, sizeof(super), &super) != sizeof(super)) {
+ DEBUG_F("read_disk_block failed!\n");
+ return 0;
+ } else if (super.sb_magicnum != XFS_SB_MAGIC) {
+ DEBUG_F("xfs_mount: Bad magic: %x\n", super.sb_magicnum);
+ return 0;
+ } else if ((super.sb_versionnum & XFS_SB_VERSION_NUMBITS) != XFS_SB_VERSION_4) {
+ DEBUG_F("xfs_mount: Bad version: %x\n", super.sb_versionnum);
+ return 0;
+ }
+
+ xfs.bsize = le32 (super.sb_blocksize);
+ xfs.blklog = super.sb_blocklog;
+ xfs.bdlog = xfs.blklog - SECTOR_BITS;
+ xfs.rootino = le64 (super.sb_rootino);
+ xfs.isize = le16 (super.sb_inodesize);
+ xfs.agblocks = le32 (super.sb_agblocks);
+ xfs.dirblklog = super.sb_dirblklog;
+ xfs.dirbsize = xfs.bsize << super.sb_dirblklog;
+
+ xfs.inopblog = super.sb_inopblog;
+ xfs.agblklog = super.sb_agblklog;
+ xfs.agnolog = xfs_highbit32 (le32 (super.sb_agcount) - 1) + 1;
+
+ xfs.btnode_ptr0_off =
+ ((xfs.bsize - sizeof(xfs_btree_block_t)) /
+ (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t)))
+ * sizeof(xfs_bmbt_key_t) + sizeof(xfs_btree_block_t);
+
+ return 1;
+}
+
+int
+xfs_read_data (char *buf, int len)
+{
+ xad_t *xad;
+ xfs_fileoff_t endofprev, endofcur, offset;
+ xfs_filblks_t xadlen;
+ int toread, startpos, endpos;
+
+ if (icore.di_format == XFS_DINODE_FMT_LOCAL) {
+ memmove(buf, inode->di_u.di_c + xfs_file->pos, len);
+ xfs_file->pos += len;
+ return len;
+ }
+
+ startpos = xfs_file->pos;
+ endpos = xfs_file->pos + len;
+ if (endpos > xfs_file->len)
+ endpos = xfs_file->len;
+ endofprev = (xfs_fileoff_t)-1;
+ init_extents ();
+ while (len > 0 && (xad = next_extent ())) {
+ offset = xad->offset;
+ xadlen = xad->len;
+ if (isinxt (xfs_file->pos >> xfs.blklog, offset, xadlen)) {
+ endofcur = (offset + xadlen) << xfs.blklog;
+ toread = (endofcur >= endpos)
+ ? len : (endofcur - xfs_file->pos);
+ read_disk_block(xfs_file, fsb2daddr (xad->start),
+ xfs_file->pos - (offset << xfs.blklog), toread, buf);
+ buf += toread;
+ len -= toread;
+ xfs_file->pos += toread;
+ } else if (offset > endofprev) {
+ toread = ((offset << xfs.blklog) >= endpos)
+ ? len : ((offset - endofprev) << xfs.blklog);
+ len -= toread;
+ xfs_file->pos += toread;
+ for (; toread; toread--) {
+ *buf++ = 0;
+ }
+ continue;
+ }
+ endofprev = offset + xadlen;
+ }
+
+ return xfs_file->pos - startpos;
+}
+
+int
+xfs_dir (char *dirname)
+{
+ xfs_ino_t ino, parent_ino, new_ino;
+ xfs_fsize_t di_size;
+ int di_mode;
+ int cmp, n, link_count;
+ char linkbuf[xfs.bsize];
+ char *rest, *name, ch;
+
+ DEBUG_ENTER;
+
+ parent_ino = ino = xfs.rootino;
+ link_count = 0;
+ for (;;) {
+ di_read (ino);
+ di_size = le64 (icore.di_size);
+ di_mode = le16 (icore.di_mode);
+
+ DEBUG_F("di_mode: %o\n", di_mode);
+ if ((di_mode & IFMT) == IFLNK) {
+ if (++link_count > MAX_LINK_COUNT) {
+ errnum = FILE_ERR_SYMLINK_LOOP;
+ DEBUG_LEAVE(FILE_ERR_SYMLINK_LOOP);
+ return 0;
+ }
+ if (di_size < xfs.bsize - 1) {
+ xfs_file->pos = 0;
+ xfs_file->len = di_size;
+ n = xfs_read_data (linkbuf, xfs_file->len);
+ } else {
+ errnum = FILE_ERR_LENGTH;
+ DEBUG_LEAVE(FILE_ERR_LENGTH);
+ return 0;
+ }
+
+ ino = (linkbuf[0] == '/') ? xfs.rootino : parent_ino;
+ while (n < (xfs.bsize - 1) && (linkbuf[n++] = *dirname++));
+ linkbuf[n] = 0;
+ dirname = linkbuf;
+ continue;
+ }
+
+ DEBUG_F("*dirname: %s\n", dirname);
+ if (!*dirname || isspace (*dirname)) {
+ if ((di_mode & IFMT) != IFREG) {
+ errnum = FILE_ERR_BAD_TYPE;
+ DEBUG_LEAVE(FILE_ERR_BAD_TYPE);
+ return 0;
+ }
+ xfs_file->pos = 0;
+ xfs_file->len = di_size;
+ DEBUG_LEAVE(1);
+ return 1;
+ }
+
+ if ((di_mode & IFMT) != IFDIR) {
+ errnum = FILE_ERR_NOTDIR;
+ DEBUG_LEAVE(FILE_ERR_NOTDIR);
+ return 0;
+ }
+
+ for (; *dirname == '/'; dirname++);
+
+ for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
+ *rest = 0;
+
+ name = first_dentry (&new_ino);
+ for (;;) {
+ cmp = (!*dirname) ? -1 : strcmp(dirname, name);
+ if (cmp == 0) {
+ parent_ino = ino;
+ if (new_ino)
+ ino = new_ino;
+ *(dirname = rest) = ch;
+ break;
+ }
+ name = next_dentry (&new_ino);
+ if (name == NULL) {
+ errnum = FILE_ERR_NOTFOUND;
+ DEBUG_LEAVE(FILE_ERR_NOTFOUND);
+ *rest = ch;
+ return 0;
+ }
+ }
+ }
+}
+
+/*
+ * Local variables:
+ * c-file-style: "K&R"
+ * c-basic-offset: 8
+ * End:
+ */
+++ /dev/null
-/* 256 color mode color table for Linux, partially borrowed from BootX */
-
-
-unsigned char color_table_red[] = {
- 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA,
- 0x55, 0x55, 0x55, 0x55, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x02, 0x9E, 0xE9, 0xC4, 0x50, 0xC9, 0xC4, 0xE9,
- 0x65, 0xE3, 0xC2, 0x25, 0xA4, 0xEC, 0x90, 0xA6,
- 0xC4, 0x6A, 0xD1, 0xF3, 0x12, 0xED, 0xA0, 0xC2,
- 0xB8, 0xD5, 0xDB, 0xD2, 0x3E, 0x16, 0xEB, 0x54,
- 0xA9, 0xCD, 0xF5, 0x0A, 0xBA, 0xB3, 0xDC, 0x74,
- 0xCE, 0xF6, 0xD3, 0xC5, 0xEA, 0xB8, 0xED, 0x5E,
- 0xE5, 0x26, 0xF4, 0xA9, 0x82, 0x94, 0xE6, 0x38,
- 0xF2, 0x0F, 0x7F, 0x49, 0xE5, 0xF4, 0xD3, 0xC3,
- 0xC2, 0x1E, 0xD5, 0xC6, 0xA4, 0xFA, 0x0A, 0xBA,
- 0xD4, 0xEB, 0xEA, 0xEC, 0xA8, 0xBC, 0xB4, 0xDC,
- 0x84, 0xE4, 0xCE, 0xEC, 0x92, 0xCD, 0xDC, 0x8B,
- 0xCC, 0x1E, 0xF6, 0xB2, 0x60, 0x2A, 0x96, 0x52,
- 0x0F, 0xBD, 0xFA, 0xCC, 0xB8, 0x7A, 0x4C, 0xD2,
- 0x06, 0xEF, 0x44, 0x64, 0xF4, 0xBA, 0xCE, 0xE6,
- 0x8A, 0x6F, 0x3C, 0x70, 0x7C, 0x9C, 0xBA, 0xDF,
- 0x2C, 0x4D, 0x3B, 0xCA, 0xDE, 0xCE, 0xEE, 0x46,
- 0x6A, 0xAC, 0x96, 0xE5, 0x96, 0x7A, 0xBA, 0xB6,
- 0xE2, 0x7E, 0xAA, 0xC5, 0x96, 0x9E, 0xC2, 0xAA,
- 0xDA, 0x35, 0xB6, 0x82, 0x88, 0xBE, 0xC2, 0x9E,
- 0xB4, 0xD5, 0xDA, 0x9C, 0xA0, 0xD0, 0xA8, 0xC7,
- 0x72, 0xF2, 0xDB, 0x76, 0xDC, 0xBE, 0xAA, 0xF4,
- 0x87, 0x2F, 0x53, 0x8E, 0x36, 0xCE, 0xE6, 0xCA,
- 0xCB, 0xE4, 0xD6, 0xAA, 0x42, 0x5D, 0xB4, 0x59,
- 0x1C, 0xC8, 0x96, 0x6C, 0xDA, 0xCE, 0xE6, 0xCB,
- 0x96, 0x16, 0xFA, 0xBE, 0xAE, 0xFE, 0x6E, 0xD6,
- 0xCE, 0xB6, 0xE5, 0xED, 0xDB, 0xDC, 0xF4, 0x72,
- 0x1F, 0xAE, 0xE6, 0xC2, 0xCA, 0xC4, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-
-unsigned char color_table_green[] = {
- 0x00, 0x00, 0xAA, 0xAA, 0x00, 0x00, 0xAA, 0xAA,
- 0x55, 0x55, 0xFF, 0xFF, 0x55, 0x55, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x02, 0x88, 0xC4, 0x85, 0x44, 0xA2, 0xA8, 0xE5,
- 0x65, 0xA6, 0xC2, 0x24, 0xA4, 0xB4, 0x62, 0x86,
- 0x94, 0x44, 0xD2, 0xB6, 0x12, 0xD4, 0x73, 0x96,
- 0x92, 0x95, 0xB2, 0xC2, 0x36, 0x0E, 0xBC, 0x54,
- 0x75, 0xA5, 0xF5, 0x0A, 0xB2, 0x83, 0xC2, 0x74,
- 0x9B, 0xBD, 0xA2, 0xCA, 0xDA, 0x8C, 0xCB, 0x42,
- 0xAC, 0x12, 0xDA, 0x7B, 0x54, 0x94, 0xD2, 0x24,
- 0xBE, 0x06, 0x65, 0x33, 0xBB, 0xBC, 0xAB, 0x8C,
- 0x92, 0x1E, 0x9B, 0xB6, 0x6E, 0xFB, 0x04, 0xA2,
- 0xC8, 0xBD, 0xAD, 0xEC, 0x92, 0xBC, 0x7B, 0x9D,
- 0x84, 0xC4, 0xC4, 0xB4, 0x6C, 0x93, 0xA3, 0x5E,
- 0x8D, 0x13, 0xD6, 0x82, 0x4C, 0x2A, 0x7A, 0x5A,
- 0x0D, 0x82, 0xBB, 0xCC, 0x8B, 0x6A, 0x3C, 0xBE,
- 0x06, 0xC4, 0x44, 0x45, 0xDB, 0x96, 0xB6, 0xDE,
- 0x8A, 0x4D, 0x3C, 0x5A, 0x7C, 0x9C, 0xAA, 0xCB,
- 0x1C, 0x4D, 0x2E, 0xB2, 0xBE, 0xAA, 0xDE, 0x3E,
- 0x6A, 0xAC, 0x82, 0xE5, 0x72, 0x62, 0x92, 0x9E,
- 0xCA, 0x4A, 0x8E, 0xBE, 0x86, 0x6B, 0xAA, 0x9A,
- 0xBE, 0x34, 0xAB, 0x76, 0x6E, 0x9A, 0x9E, 0x62,
- 0x76, 0xCE, 0xD3, 0x92, 0x7C, 0xB8, 0x7E, 0xC6,
- 0x5E, 0xE2, 0xC3, 0x54, 0xAA, 0x9E, 0x8A, 0xCA,
- 0x63, 0x2D, 0x3B, 0x8E, 0x1A, 0x9E, 0xC2, 0xA6,
- 0xCB, 0xDC, 0xD6, 0x8E, 0x26, 0x5C, 0xB4, 0x45,
- 0x1C, 0xB8, 0x6E, 0x4C, 0xBC, 0xAE, 0xD6, 0x92,
- 0x63, 0x16, 0xF6, 0x8C, 0x7A, 0xFE, 0x6E, 0xBA,
- 0xC6, 0x86, 0xAA, 0xAE, 0xDB, 0xA4, 0xD4, 0x56,
- 0x0E, 0x6E, 0xB6, 0xB2, 0xBE, 0xBE, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-
-
-unsigned char color_table_blue[] = {
- 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA,
- 0x55, 0xFF, 0x55, 0xFF, 0x55, 0xFF, 0x55, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x04, 0x28, 0x10, 0x0B, 0x14, 0x14, 0x74, 0xC7,
- 0x64, 0x0E, 0xC3, 0x24, 0xA4, 0x0C, 0x10, 0x20,
- 0x0D, 0x04, 0xD1, 0x0D, 0x13, 0x22, 0x0A, 0x40,
- 0x14, 0x0C, 0x11, 0x94, 0x0C, 0x08, 0x0B, 0x56,
- 0x09, 0x47, 0xF4, 0x0B, 0x9C, 0x07, 0x54, 0x74,
- 0x0F, 0x0C, 0x0F, 0xC7, 0x6C, 0x14, 0x14, 0x11,
- 0x0B, 0x04, 0x12, 0x0C, 0x05, 0x94, 0x94, 0x0A,
- 0x34, 0x09, 0x14, 0x08, 0x2F, 0x15, 0x19, 0x11,
- 0x28, 0x0C, 0x0B, 0x94, 0x08, 0xFA, 0x08, 0x7C,
- 0xBC, 0x15, 0x0A, 0xEC, 0x64, 0xBB, 0x0A, 0x0C,
- 0x84, 0x2C, 0xA0, 0x15, 0x10, 0x0D, 0x0B, 0x0E,
- 0x0A, 0x07, 0x10, 0x3C, 0x24, 0x2C, 0x28, 0x5C,
- 0x0A, 0x0D, 0x0A, 0xC1, 0x22, 0x4C, 0x10, 0x94,
- 0x04, 0x0F, 0x45, 0x08, 0x31, 0x54, 0x3C, 0xBC,
- 0x8C, 0x09, 0x3C, 0x18, 0x7C, 0x9C, 0x7C, 0x91,
- 0x0C, 0x4D, 0x17, 0x74, 0x0C, 0x48, 0x9C, 0x3C,
- 0x6A, 0xAC, 0x5C, 0xE3, 0x29, 0x3C, 0x2C, 0x7C,
- 0x6C, 0x04, 0x14, 0xA9, 0x74, 0x07, 0x2C, 0x74,
- 0x4C, 0x34, 0x97, 0x5C, 0x38, 0x0C, 0x5C, 0x04,
- 0x0C, 0xBA, 0xBC, 0x78, 0x18, 0x88, 0x24, 0xC2,
- 0x3C, 0xB4, 0x87, 0x0C, 0x14, 0x4C, 0x3C, 0x10,
- 0x17, 0x2C, 0x0A, 0x8C, 0x04, 0x1C, 0x44, 0x2C,
- 0xCD, 0xD8, 0xD4, 0x34, 0x0C, 0x5B, 0xB4, 0x1E,
- 0x1D, 0xAC, 0x24, 0x18, 0x20, 0x5C, 0xB4, 0x1C,
- 0x09, 0x14, 0xFC, 0x0C, 0x10, 0xFC, 0x6C, 0x7C,
- 0xB4, 0x1C, 0x15, 0x17, 0xDB, 0x18, 0x21, 0x24,
- 0x04, 0x04, 0x44, 0x8C, 0x8C, 0xB7, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
+++ /dev/null
-/* effects.c */
-/* Adds splash screen and status bar effects for graphical yaboot */
-
-#include "file.h"
-#include "yaboot.h"
-#include "stdlib.h"
-
-#define SB_XSTART 170
-#define SB_XEND 472
-#define SB_YSTART 402
-
-unsigned char bar_grad[] = { 228, 237, 246, 254, 207, 254, 246, 237, 228, 206 };
-
-int scrOpen(void);
-void scrSetEntireColorMap(unsigned char *);
-void scrClear(unsigned char);
-void pcxDisplay(unsigned char *, unsigned int);
-void scrFadeColorMap(unsigned char *, unsigned char *, int);
-unsigned char *pcxColormap(unsigned char *, int);
-void scrPutPixel(int, int, unsigned char);
-
-void fxDisplaySplash(struct boot_fspec_t *filespec)
-{
- void *gfx_file;
- int gfx_len;
- unsigned char *grey_map;
- int start_time;
- struct boot_file_t file;
- int result;
- static int been_here = 0;
-
- if(!been_here)
- {
- been_here = 1;
- gfx_file = (void *) malloc(1024 * 512);
- if (gfx_file == NULL) {
- prom_printf("malloc failed in fxDisplaySplash()\n");
- return;
- }
-
- scrOpen();
-
- result = open_file(filespec, &file);
-
- if(result != FILE_ERR_OK)
- {
- prom_printf("Error loading splash screen\n");
- return;
- }
-
- gfx_len = file.fs->read(&file, 1024 * 512 - 765, gfx_file);
- file.fs->close(&file);
- grey_map = gfx_file + gfx_len;
- memset(grey_map, 0/*128*/, 765);
- }
-
- scrSetEntireColorMap(grey_map);
- scrClear(0);
-
- start_time = prom_getms();
- while(prom_getms() < start_time + 2000);
-
- pcxDisplay(gfx_file, gfx_len);
- scrFadeColorMap(grey_map, pcxColormap( gfx_file, gfx_len ), 2);
-}
-
-
-void fxUpdateSB(unsigned number, unsigned total)
-{
- int x, y;
-
- for(x = SB_XSTART; x < SB_XSTART + (SB_XEND - SB_XSTART) * number / total; ++x)
- {
- for(y = 0; y < 10; ++y)
- scrPutPixel(x, SB_YSTART + y, bar_grad[y]);
- }
-}
-
-
-#define BLOCK_INDEX (1024 * 64)
-
-int fxReadImage(struct boot_file_t *file, unsigned int filesize, void *base)
-{
- unsigned int count, result = 0;
-
- for(count = 0; count < filesize; count += result)
- {
- result = ((filesize - count) < BLOCK_INDEX) ? (filesize - count) : BLOCK_INDEX;
- if ((result = file->fs->read(file, result, base + count)) != BLOCK_INDEX)
- break;
- fxUpdateSB(count + result, filesize);
- }
- fxUpdateSB(count + result, filesize);
- return(count + result);
-}
+++ /dev/null
-/* Crude PCX file loading and display for 640x480 image at boot */
-
-unsigned char *pcxColormap(unsigned char *gfx_file, int gfx_len)
-{
- return(gfx_file + gfx_len - 768);
-}
-
-extern void scrPutPixel( int x, int y, unsigned char c );
-
-static void inline do_putpixel(int offset, unsigned char c)
-{
- scrPutPixel(offset % 640, offset / 640, c);
-}
-
-void pcxDisplay(unsigned char *gfx_file, unsigned gfx_len)
-{
- int offset, file_offset, i, c, f;
-
- for(offset = 0, file_offset = 128; offset < 640 * 480 && file_offset < gfx_len - 769; file_offset++)
- {
- if(((c = gfx_file[file_offset]) & 0xc0) == 0xc0)
- {
- f = gfx_file[++file_offset];
- c &= 0x3f;
- for(i = 0; i < c; ++i)
- do_putpixel(offset++, f);
- }
- else
- do_putpixel(offset++, c);
- }
-}
+++ /dev/null
-#include "prom.h"
-
-#define WINDOW_X_SIZE 640
-#define WINDOW_Y_SIZE 480
-
-
-static prom_handle videodev;
-static prom_handle videop;
-static int Xres, Yres;
-static int Xstart, Ystart;
-static int rowbytes;
-static int zoom;
-static unsigned char *address;
-
-static int scrSetColorMap( unsigned char color,
- unsigned char r, unsigned char g, unsigned char b );
-
-
-int scrOpen()
-{
- int result = 0;
-
- videodev = (prom_handle)call_prom( "open", 1, 1, "screen" );
- if( videodev == PROM_INVALID_HANDLE )
- return(-1);
- videop = (prom_handle)call_prom( "instance-to-package", 1, 1, videodev );
- if( videop == PROM_INVALID_HANDLE )
- return(-1);
-
- result |= prom_getprop(videop, "width", &Xres, 4 );
- result |= prom_getprop(videop, "height", &Yres, 4 );
- result |= prom_getprop(videop, "address", &address, 4 );
- result |= prom_getprop(videop, "linebytes", &rowbytes, 4 );
-
- prom_map (address, address, rowbytes * Xres);
-
-#if DEBUG
- prom_printf("width : %d\n", Xres);
- prom_printf("height : %d\n", Yres);
- prom_printf("address : 0x%08lx\n", address);
- prom_printf("linebytes : %d\n", rowbytes);
- prom_printf("result : %d\n", result);
-#endif
-
- if( result < 0 )
- return( -1 );
-
- zoom = Xres / WINDOW_X_SIZE > Yres / WINDOW_Y_SIZE ? Yres / WINDOW_Y_SIZE : Xres / WINDOW_X_SIZE;
-
- Xstart = Xres / 2 - WINDOW_X_SIZE / 2 * zoom;
- Ystart = Yres / 2 - WINDOW_Y_SIZE / 2 * zoom;
-
-#if DEBUG
- prom_printf("zoom : %d\n", zoom);
- prom_printf("Xstart : %d\n", Xstart);
- prom_printf("Ystart : %d\n", Ystart);
-#endif
-
- return( 0 );
-}
-
-
-void scrClear( unsigned char c )
-{
- int x, y;
-
- for (y = 0; y < Yres; y++)
- for (x = 0; x < Xres; x++)
- address[y * rowbytes + x] = c;
-}
-
-
-void scrClose()
-{
- call_prom( "close", 1, 0, videodev );
- videodev = 0;
-}
-
-
-void scrReset()
-{
- int c;
- extern unsigned char color_table_red[],
- color_table_green[],
- color_table_blue[];
-
- for( c = 0; c < 16; ++c )
- scrSetColorMap( c, color_table_red[c],
- color_table_green[c],
- color_table_blue[c] );
-// scrClose();
-}
-
-static void inline do_pix( int x, int y, unsigned char c )
-{
- address[ y * rowbytes + x ] = c;
-}
-
-
-void scrPutPixel( int x, int y, unsigned char c )
-{
- int zx, zy;
-
- for( zy = 0; zy < zoom; ++zy )
- for( zx = 0; zx < zoom; ++zx )
- do_pix( x * zoom + zx + Xstart, y * zoom + zy + Ystart, c );
-}
-
-
-int scrSetColorMap( unsigned char color, unsigned char r, unsigned char g, unsigned char b )
-{
- int result;
-
- result = (int)call_prom( "call-method", 6, 1, "color!", videodev, color, b, g, r );
-
- return( result );
-}
-
-
-void scrFillColorMap( unsigned char r, unsigned char g, unsigned char b )
-{
- int c;
-
- for( c = 0; c < 256; ++c )
- scrSetColorMap( c, r, g, b );
-}
-
-
-void scrSetEntireColorMap( unsigned char *map )
-{
- int c;
-
- for( c = 0; c < 256; ++c )
- scrSetColorMap( c, map[c * 3], map[c * 3 + 1], map[c * 3 + 2] );
-}
-
-
-void scrFadeColorMap( unsigned char *first, unsigned char *last, int rate )
-{
- int inc, c;
-
- for( inc = 0; inc < 256; inc += rate )
- for( c = 0; c < 256; ++c )
- scrSetColorMap( c, first[c * 3 + 0] * (255 - inc) / 255 + last[c * 3 + 0] * inc / 255,
- first[c * 3 + 1] * (255 - inc) / 255 + last[c * 3 + 1] * inc / 255,
- first[c * 3 + 2] * (255 - inc) / 255 + last[c * 3 + 2] * inc / 255 );
-}
if (prom_blksize <= 1)
prom_blksize = 512;
if (prom_blksize > MAX_BLOCK_SIZE) {
- prom_printf("block_size %d not supported !\n");
+ prom_printf("block_size %d not supported !\n", prom_blksize);
goto bail;
}
prom_blksize);
prom_printf("ISO9660 disk\n");
} else {
- prom_printf("Not a macintosh-formatted disk !\n");
+ prom_printf("No supported partition table detected\n");
goto bail;
}
#include "types.h"
#include "ctype.h"
#include "asm/processor.h"
+#include "errors.h"
#define READ_BLOCKS_USE_READ 1
if (prom_args.args[2+nargs] != 0)
{
- prom_printf ("method '%s' failed %d\n", method, prom_args.args[2+nargs]);
+ prom_printf ("method '%s' failed %p\n", method, prom_args.args[2+nargs]);
return 0;
}
return prom_args.args[2+nargs+1];
void
prom_vfprintf (prom_handle file, char *fmt, va_list ap)
{
- static char printf_buf[1024];
+ static char printf_buf[1536];
vsprintf (printf_buf, fmt, ap);
prom_puts (file, printf_buf);
}
void
prom_vprintf (char *fmt, va_list ap)
{
- static char printf_buf[1024];
+ static char printf_buf[1536];
vsprintf (printf_buf, fmt, ap);
prom_puts (prom_stdout, printf_buf);
}
va_end (ap);
}
+void
+prom_perror (int error, char *filename)
+{
+ if (error == FILE_ERR_EOF)
+ prom_printf("%s: Unexpected End Of File\n", filename);
+ else if (error == FILE_ERR_NOTFOUND)
+ prom_printf("%s: No such file or directory\n", filename);
+ else if (error == FILE_CANT_SEEK)
+ prom_printf("%s: Seek error\n", filename);
+ else if (error == FILE_IOERR)
+ prom_printf("%s: Input/output error\n", filename);
+ else if (error == FILE_BAD_PATH)
+ prom_printf("%s: Path too long\n", filename);
+ else if (error == FILE_ERR_BAD_TYPE)
+ prom_printf("%s: Not a regular file\n", filename);
+ else if (error == FILE_ERR_NOTDIR)
+ prom_printf("%s: Not a directory\n", filename);
+ else if (error == FILE_ERR_BAD_FSYS)
+ prom_printf("%s: Unknown or corrupt filesystem\n", filename);
+ else if (error == FILE_ERR_SYMLINK_LOOP)
+ prom_printf("%s: Too many levels of symbolic links\n", filename);
+ else if (error == FILE_ERR_LENGTH)
+ prom_printf("%s: File too large\n", filename);
+ else if (error == FILE_ERR_FSBUSY)
+ prom_printf("%s: Filesystem busy\n", filename);
+ else if (error == FILE_ERR_BADDEV)
+ prom_printf("%s: Unable to open file, Invalid device\n", filename);
+ else
+ prom_printf("%s: Unknown error\n", filename);
+}
+
void
prom_readline (char *prompt, char *buf, int len)
{
prom_exit ();
}
+void
+prom_sleep (int seconds)
+{
+ int end;
+ end = (prom_getms() + (seconds * 1000));
+ while (prom_getms() <= end);
+}
+
void *
prom_claim (void *virt, unsigned int size, unsigned int align)
{
#include "stdlib.h"
#include "prom.h"
#include "file.h"
+#include "errors.h"
#include "cfg.h"
#include "cmdline.h"
#include "yaboot.h"
#define CONFIG_FILE_NAME "yaboot.conf"
#define CONFIG_FILE_MAX 0x8000 /* 32k */
-#ifdef CONFIG_SPLASH_SCREEN
-#include "gui.h"
-#endif /* CONFIG_SPLASH_SCREEN */
-
#ifdef USE_MD5_PASSWORDS
#include "md5.h"
#endif /* USE_MD5_PASSWORDS */
int useconf = 0;
char bootdevice[1024];
-char *bootpath = NULL;
+//char *bootpath = NULL;
char *password = NULL;
-int bootpartition = -1;
+//int bootpartition = -1;
+struct boot_fspec_t boot;
int _machine = _MACH_Pmac;
#ifdef CONFIG_COLOR_TEXT
/* Allocate some memory for malloc'ator */
malloc_base = prom_claim((void *)MALLOCADDR, MALLOCSIZE, 0);
if (malloc_base == (void *)-1) {
- prom_printf("Can't claim malloc buffer (%d bytes at 0x%08lx)\n",
+ prom_printf("Can't claim malloc buffer (%d bytes at 0x%08x)\n",
MALLOCSIZE, MALLOCADDR);
return -1;
}
malloc_init(malloc_base, MALLOCSIZE);
-#if DEBUG
- prom_printf("Malloc buffer allocated at 0x%x (%d bytes)\n",
+ DEBUG_F("Malloc buffer allocated at %p (%d bytes)\n",
malloc_base, MALLOCSIZE);
-#endif
- /* A few useless printf's */
-#if DEBUG
- prom_printf("reloc_offset : %ld (should be 0)\n", reloc_offset());
- prom_printf("test_bss : %d (should be 0)\n", test_bss);
- prom_printf("test_data : %d (should be 0)\n", test_data);
- prom_printf("&test_data : 0x%08lx\n", &test_data);
- prom_printf("&test_bss : 0x%08lx\n", &test_bss);
- prom_printf("linked at : 0x%08lx\n", TEXTADDR);
-#endif
+ /* A few useless DEBUG_F's */
+ DEBUG_F("reloc_offset : %ld (should be 0)\n", reloc_offset());
+ DEBUG_F("test_bss : %d (should be 0)\n", test_bss);
+ DEBUG_F("test_data : %d (should be 0)\n", test_data);
+ DEBUG_F("&test_data : %p\n", &test_data);
+ DEBUG_F("&test_bss : %p\n", &test_bss);
+ DEBUG_F("linked at : 0x%08x\n", TEXTADDR);
+
/* ask the OF info if we're a chrp or pmac */
/* we need to set _machine before calling finish_device_tree */
root = prom_finddevice("/");
}
}
-#if DEBUG
- prom_printf("Running on _machine = %d\n", _machine);
-#endif
+ DEBUG_F("Running on _machine = %d\n", _machine);
+ DEBUG_SLEEP;
/* Call out main */
result = yaboot_main();
/* Get rid of malloc pool */
malloc_dispose();
prom_release(malloc_base, MALLOCSIZE);
-#if DEBUG
- prom_printf("Malloc buffer released. Exiting with code %d\n",
+ DEBUG_F("Malloc buffer released. Exiting with code %d\n",
result);
-#endif
-
/* Return to OF */
prom_exit();
goto bail;
}
-#if DEBUG
- prom_printf("Config file successfully parsed\n", sz);
-#endif
+ DEBUG_F("Config file successfully parsed, %d bytes\n", sz);
/* Now, we do the initialisations stored in the config file */
p = cfg_get_strg(0, "init-code");
#ifdef CONFIG_COLOR_TEXT
p = cfg_get_strg(0, "fgcolor");
if (p) {
-#if DEBUG
- prom_printf("fgcolor=%s\n", p);
-#endif
+ DEBUG_F("fgcolor=%s\n", p);
fgcolor = check_color_text_ui(p);
if (fgcolor == -1) {
prom_printf("Invalid fgcolor: \"%s\".\n", p);
}
p = cfg_get_strg(0, "bgcolor");
if (p) {
-#if DEBUG
- prom_printf("bgcolor=%s\n", p);
-#endif
+ DEBUG_F("bgcolor=%s\n", p);
bgcolor = check_color_text_ui(p);
if (bgcolor == -1)
prom_printf("Invalid bgcolor: \"%s\".\n", p);
prom_interpret(temp);
#if !DEBUG
prom_printf("\xc");
-#endif
+#endif /* !DEBUG */
}
if (fgcolor >= 0) {
char temp[64];
void check_password(char *str)
{
- int i, end;
+ int i;
for (i = 0; i < 3; i++) {
prom_printf ("\n%sassword: ", str);
}
else if (!strcmp (password, passwdbuff))
return;
-#else
+#else /* !MD5 */
if (!strcmp (password, passwdbuff))
return;
-#endif
+#endif /* USE_MD5_PASSWORDS */
if (i < 2)
prom_printf ("Password incorrect. Please try again...");
}
prom_printf ("Seems like you don't know the access password. Go away!\n");
- end = (prom_getms() + 3000);
- while (prom_getms() <= end);
+ prom_sleep(3);
prom_interpret("reset-all");
}
static char imagepath[1024];
static char initrdpath[1024];
static char sysmappath[1024];
-#ifdef CONFIG_SPLASH_SCREEN
- static char splashpath[1024];
-#endif /* CONFIG_SPLASH_SCREEN */
pause_after = 0;
memset(params, 0, sizeof(*params));
params->kernel.part = -1;
params->rd.part = -1;
params->sysmap.part = -1;
- params->splash.part = -1;
- defpart = bootpartition;
+ defpart = boot.part;
cmdinit();
word_split(&imagename, ¶ms->args);
timeout = DEFAULT_TIMEOUT;
if (imagename) {
- prom_printf("Default supplied on the command line: ");
- prom_printf("%s ", imagename);
+ prom_printf("Default supplied on the command line: %s ", imagename);
if (params->args)
prom_printf("%s", params->args);
prom_printf("\n");
imagename = cfg_get_default();
label = 0;
- defdevice = bootdevice;
+ defdevice = boot.dev;
if (useconf) {
defdevice = cfg_get_strg(0, "device");
label = imagename;
imagename = p;
defdevice = cfg_get_strg(label, "device");
- if(!defdevice) defdevice=bootdevice;
+ if(!defdevice) defdevice=boot.dev;
p = cfg_get_strg(label, "partition");
if (p) {
n = simple_strtol(p, &endp, 10);
}
}
+ if (!strcmp (imagename, "help")) {
+ prom_printf(
+ "\nPress the tab key for a list of defined images.\n"
+ "The label marked with a \"*\" is is the default image, "
+ "press <return> to boot it.\n\n"
+ "To boot any other label simply type its name and press <return>.\n\n"
+ "To boot a kernel image which is not defined in the yaboot configuration \n"
+ "file, enter the kernel image name as [device:][partno],/path, where \n"
+ "\"device:\" is the OpenFirmware device path to the disk the image \n"
+ "resides on, and \"partno\" is the partition number the image resides on.\n\n"
+ "If you omit \"device:\" and \"partno\" yaboot will use the values of \n"
+ "\"device=\" and \"partition=\" in yaboot.conf, right now those are set to: \n"
+ "device=%s\n"
+ "partition=%d\n\n", defdevice, defpart);
+ return 0;
+ }
+
if (!strcmp (imagename, "halt")) {
if (password)
check_password ("P");
if (!label && password)
check_password ("To boot a custom image you must enter the p");
- params->kernel.dev = parse_device_path(imagepath, ¶ms->kernel.file,
- ¶ms->kernel.part);
- if (validate_fspec(¶ms->kernel, defdevice, defpart) != FILE_ERR_OK) {
- prom_printf(
-"Enter the kernel image name as [device:][partno]/path, where partno is a\n"
-"number from 0 to 16. Instead of /path you can type [mm-nn] to specify a\n"
-"range of disk blocks (512B)\n"
-"Example: hd:3,/vmlinux\n");
- return 0;
+ if (!parse_device_path(imagepath, defdevice, defpart,
+ "/vmlinux", ¶ms->kernel)) {
+ prom_printf("%s: Unable to parse\n", imagepath);
+ return 0;
}
+ DEBUG_F("after parse_device_path: dev=%s part=%d file=%s\n", params->kernel.dev,
+ params->kernel.part, params->kernel.file);
if (useconf) {
p = cfg_get_strg(label, "initrd");
if (p && *p) {
-#if DEBUG
- prom_printf("parsing initrd path <%s>\n", p);
-#endif
+ DEBUG_F("Parsing initrd path <%s>\n", p);
strncpy(initrdpath, p, 1024);
- params->rd.dev = parse_device_path(initrdpath,
- ¶ms->rd.file, ¶ms->rd.part);
- validate_fspec(¶ms->rd, defdevice, defpart);
+ if (!parse_device_path(initrdpath, defdevice, defpart,
+ "/root.bin", ¶ms->rd)) {
+ prom_printf("%s: Unable to parse\n", imagepath);
+ return 0;
+ }
}
p = cfg_get_strg(label, "sysmap");
if (p && *p) {
-#if DEBUG
- prom_printf("parsing sysmap path <%s>\n", p);
-#endif
+ DEBUG_F("Parsing sysmap path <%s>\n", p);
strncpy(sysmappath, p, 1024);
- params->sysmap.dev = parse_device_path(sysmappath,
- ¶ms->sysmap.file, ¶ms->sysmap.part);
- validate_fspec(¶ms->sysmap, defdevice, defpart);
- }
-#ifdef CONFIG_SPLASH_SCREEN
- p = cfg_get_strg(label, "splash");
- if (p && *p) {
-#if DEBUG
- prom_printf("parsing splash path <%s>\n", p);
-#endif
- strncpy(splashpath, p, 1024);
- params->splash.dev = parse_device_path(splashpath,
- ¶ms->splash.file, ¶ms->splash.part);
- validate_fspec(¶ms->splash, defdevice, defpart);
+ if (!parse_device_path(sysmappath, defdevice, defpart,
+ "/boot/System.map", ¶ms->sysmap)) {
+ prom_printf("%s: Unable to parse\n", imagepath);
+ return 0;
+ }
}
-#endif /* CONFIG_SPLASH_SCREEN */
- }
-
+ }
return 0;
}
if (!params.kernel.file)
continue;
-#ifdef CONFIG_SPLASH_SCREEN
- if (params.splash.file)
- fxDisplaySplash(¶ms.splash);
-#endif /* CONFIG_SPLASH_SCREEN */
prom_printf("Please wait, loading kernel...\n");
- if(bootpath && !strcmp(bootpath,"\\\\") && params.kernel.file[0] != '/') {
- loc=(char*)malloc(strlen(params.kernel.file)+3);
- if (!loc) {
- prom_printf ("malloc error\n");
- goto next;
- }
- strcpy(loc,bootpath);
- strcat(loc,params.kernel.file);
- free(params.kernel.file);
- params.kernel.file=loc;
+ memset(&file, 0, sizeof(file));
+
+ if (strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.kernel.file[0] != '/'
+ && params.kernel.file[0] != '\\') {
+ loc=(char*)malloc(strlen(params.kernel.file)+3);
+ if (!loc) {
+ prom_printf ("malloc error\n");
+ goto next;
+ }
+ strcpy(loc,boot.file);
+ strcat(loc,params.kernel.file);
+ free(params.kernel.file);
+ params.kernel.file=loc;
}
result = open_file(¶ms.kernel, &file);
if (result != FILE_ERR_OK) {
- prom_printf("\nImage not found.... try again\n");
- goto next;
+ prom_printf("%s:%d,", params.kernel.dev, params.kernel.part);
+ prom_perror(result, params.kernel.file);
+ goto next;
}
/* Read the Elf e_ident, e_type and e_machine fields to
* determine Elf file type
*/
if (file.fs->read(&file, sizeof(Elf_Ident), &loadinfo.elf) < sizeof(Elf_Ident)) {
- prom_printf("\nCan't read Elf e_ident/e_type/e_machine info\n");
- goto next;
+ prom_printf("\nCan't read Elf e_ident/e_type/e_machine info\n");
+ file.fs->close(&file);
+ memset(&file, 0, sizeof(file));
+ goto next;
}
- if ( is_elf32(&loadinfo) ) {
- if ( !load_elf32(&file, &loadinfo) )
- goto next;
- prom_printf(" Elf32 kernel loaded...\n");
- } else if ( is_elf64(&loadinfo) ) {
- if ( !load_elf64(&file, &loadinfo) )
- goto next;
- prom_printf(" Elf64 kernel loaded...\n");
+ if (is_elf32(&loadinfo)) {
+ if (!load_elf32(&file, &loadinfo)) {
+ file.fs->close(&file);
+ memset(&file, 0, sizeof(file));
+ goto next;
+ }
+ prom_printf(" Elf32 kernel loaded...\n");
+ } else if (is_elf64(&loadinfo)) {
+ if (!load_elf64(&file, &loadinfo)) {
+ file.fs->close(&file);
+ memset(&file, 0, sizeof(file));
+ goto next;
+ }
+ prom_printf(" Elf64 kernel loaded...\n");
} else {
- prom_printf ("Not a valid ELF image\n");
- goto next;
+ prom_printf ("%s: Not a valid ELF image\n", params.kernel.file);
+ file.fs->close(&file);
+ memset(&file, 0, sizeof(file));
+ goto next;
}
file.fs->close(&file);
+ memset(&file, 0, sizeof(file));
/* If sysmap, load it.
*/
if (params.sysmap.file) {
- prom_printf("Loading System.map ...\n");
- if(bootpath && !strcmp(bootpath,"\\\\") && params.sysmap.file[0] != '/') {
- if (loc) free(loc);
- loc=(char*)malloc(strlen(params.sysmap.file)+3);
- if (!loc) {
- prom_printf ("malloc error\n");
- goto next;
- }
- strcpy(loc,bootpath);
- strcat(loc,params.sysmap.file);
- free(params.sysmap.file);
- params.sysmap.file=loc;
- }
-
- result = open_file(¶ms.sysmap, &file);
- if (result != FILE_ERR_OK)
- prom_printf("\nSystem.map file not found.\n");
- else {
- sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0);
- if (sysmap_base == (void *)-1) {
- prom_printf("claim failed for sysmap memory\n");
- sysmap_base = 0;
- } else {
- sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base);
- if (sysmap_size == 0)
- sysmap_base = 0;
- else
- ((char *)sysmap_base)[sysmap_size++] = 0;
- }
- file.fs->close(&file);
- }
- if (sysmap_base) {
- prom_printf("System.map loaded at 0x%08lx, size: %d Kbytes\n",
- sysmap_base, sysmap_size >> 10);
- loadinfo.memsize += _ALIGN(0x100000, 0x1000);
- } else {
- prom_printf("System.map load failed !\n");
- prom_pause();
- }
+ prom_printf("Loading System.map ...\n");
+ if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.sysmap.file[0] != '/'
+ && params.sysmap.file[0] != '\\') {
+ if (loc) free(loc);
+ loc=(char*)malloc(strlen(params.sysmap.file)+3);
+ if (!loc) {
+ prom_printf ("malloc error\n");
+ goto next;
+ }
+ strcpy(loc,boot.file);
+ strcat(loc,params.sysmap.file);
+ free(params.sysmap.file);
+ params.sysmap.file=loc;
+ }
+
+ result = open_file(¶ms.sysmap, &file);
+ if (result != FILE_ERR_OK) {
+ prom_printf("%s:%d,", params.sysmap.dev, params.sysmap.part);
+ prom_perror(result, params.sysmap.file);
+ }
+ else {
+ sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0);
+ if (sysmap_base == (void *)-1) {
+ prom_printf("Claim failed for sysmap memory\n");
+ sysmap_base = 0;
+ } else {
+ sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base);
+ if (sysmap_size == 0)
+ sysmap_base = 0;
+ else
+ ((char *)sysmap_base)[sysmap_size++] = 0;
+ }
+ file.fs->close(&file);
+ memset(&file, 0, sizeof(file));
+ }
+ if (sysmap_base) {
+ prom_printf("System.map loaded at %p, size: %lu Kbytes\n",
+ sysmap_base, sysmap_size >> 10);
+ loadinfo.memsize += _ALIGN(0x100000, 0x1000);
+ } else {
+ prom_printf("System.map load failed !\n");
+ prom_pause();
+ }
}
/* If ramdisk, load it. For now, we can't tell the size it will be
* so we claim an arbitrary amount of 4Mb
*/
if (params.rd.file) {
- if(bootpath && !strcmp(bootpath,"\\\\") && params.rd.file[0] != '/')
+ if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.rd.file[0] != '/'
+ && params.kernel.file[0] != '\\')
{
if (loc) free(loc);
loc=(char*)malloc(strlen(params.rd.file)+3);
if (!loc) {
- prom_printf ("malloc error\n");
+ prom_printf ("Malloc error\n");
goto next;
}
- strcpy(loc,bootpath);
+ strcpy(loc,boot.file);
strcat(loc,params.rd.file);
free(params.rd.file);
params.rd.file=loc;
}
prom_printf("Loading ramdisk...\n");
result = open_file(¶ms.rd, &file);
- if (result != FILE_ERR_OK)
- prom_printf("\nRamdisk image not found.\n");
+ if (result != FILE_ERR_OK) {
+ prom_printf("%s:%d,", params.rd.dev, params.rd.part);
+ prom_perror(result, params.rd.file);
+ }
else {
#define INITRD_CHUNKSIZE 0x400000
initrd_base = prom_claim(loadinfo.base+loadinfo.memsize, INITRD_CHUNKSIZE, 0);
if (initrd_base == (void *)-1) {
- prom_printf("claim failed for initrd memory\n");
+ prom_printf("Claim failed for initrd memory\n");
initrd_base = 0;
} else {
initrd_size = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_base);
initrd_want = (void *)((unsigned long)initrd_more+INITRD_CHUNKSIZE);
initrd_more = prom_claim(initrd_want, INITRD_CHUNKSIZE, 0);
if (initrd_more != initrd_want) {
- prom_printf("claim failed for initrd memory at %x rc=%x\n",initrd_want,initrd_more);
+ prom_printf("Claim failed for initrd memory at %p rc=%p\n",initrd_want,initrd_more);
break;
}
initrd_read = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_more);
-#if DEBUG
- prom_printf(" block at %x rc=%x\n",initrd_more,initrd_read);
-#endif
+ DEBUG_F(" block at %p rc=%lu\n",initrd_more,initrd_read);
initrd_size += initrd_read;
}
}
file.fs->close(&file);
+ memset(&file, 0, sizeof(file));
}
if (initrd_base)
- prom_printf("ramdisk loaded at 0x%08lx, size: %d Kbytes\n",
+ prom_printf("ramdisk loaded at %p, size: %lu Kbytes\n",
initrd_base, initrd_size >> 10);
else {
prom_printf("ramdisk load failed !\n");
}
}
-#if DEBUG
- prom_printf("setting kernel args to: %s\n", params.args);
-#endif
+ DEBUG_F("setting kernel args to: %s\n", params.args);
prom_setargs(params.args);
-#if DEBUG
- prom_printf("flushing icache...");
-#endif
+ DEBUG_F("flushing icache...");
flush_icache_range ((long)loadinfo.base, (long)loadinfo.base+loadinfo.memsize);
-#if DEBUG
- prom_printf(" done\n");
-#endif
+ DEBUG_F(" done\n");
/*
* Fill mew boot infos
* by the malloc pool
*/
prom_map (birec, birec, 0x10000);
-#if DEBUG
- prom_printf("birec at 0x%08lx\n", birec);
- {
- int i = prom_getms();
- while((prom_getms() - i) < 2000)
- ;
- }
-#endif
+ DEBUG_F("birec at %p\n", birec);
+ DEBUG_SLEEP;
birec->tag = BI_FIRST;
birec->size = sizeof(struct bi_record);
/* compute the kernel's entry point. */
kernel_entry = loadinfo.base + loadinfo.entry - loadinfo.load_loc;
-#if DEBUG
- prom_printf("Kernel entry point = 0x%08lx\n", kernel_entry);
- prom_printf("kernel: arg1 = 0x%08lx,\n"
- " arg2 = 0x%08lx,\n"
- " prom = 0x%08lx,\n"
- " arg4 = 0x%08lx,\n"
- " arg5 = 0x%08lx\n\n",
+ DEBUG_F("Kernel entry point = %p\n", kernel_entry);
+ DEBUG_F("kernel: arg1 = %p,\n"
+ " arg2 = 0x%08lx,\n"
+ " prom = %p,\n"
+ " arg4 = %d,\n"
+ " arg5 = %d\n\n",
initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
-#endif
+ DEBUG_F("Entering kernel...\n");
-#if DEBUG
- prom_printf("entering kernel...\n");
-#endif
/* call the kernel with our stack. */
kernel_entry(initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
continue;
next:
- if( file.fs != NULL )
- file.fs->close(&file);
+ ; /* do nothing */
}
}
return 0;
}
-#if DEBUG
- prom_printf("Elf32 header:\n");
- prom_printf(" e.e_type = %d\n", (int)e->e_type);
- prom_printf(" e.e_machine = %d\n", (int)e->e_machine);
- prom_printf(" e.e_version = %d\n", (int)e->e_version);
- prom_printf(" e.e_entry = 0x%08x\n", (int)e->e_entry);
- prom_printf(" e.e_phoff = 0x%08x\n", (int)e->e_phoff);
- prom_printf(" e.e_shoff = 0x%08x\n", (int)e->e_shoff);
- prom_printf(" e.e_flags = %d\n", (int)e->e_flags);
- prom_printf(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
- prom_printf(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
- prom_printf(" e.e_phnum = %d\n", (int)e->e_phnum);
-#endif
+ DEBUG_F("Elf32 header:\n");
+ DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
+ DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
+ DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
+ DEBUG_F(" e.e_entry = 0x%08x\n", (int)e->e_entry);
+ DEBUG_F(" e.e_phoff = 0x%08x\n", (int)e->e_phoff);
+ DEBUG_F(" e.e_shoff = 0x%08x\n", (int)e->e_shoff);
+ DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
+ DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
+ DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
+ DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
loadinfo->entry = e->e_entry;
if (e->e_phnum > MAX_HEADERS) {
- prom_printf ("can only load kernels with one program header\n");
+ prom_printf ("Can only load kernels with one program header\n");
return 0;
}
ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * e->e_phnum);
if (!ph) {
- prom_printf ("malloc error\n");
+ prom_printf ("Malloc error\n");
return 0;
}
/* leave some room (1Mb) for boot infos */
loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
/* Claim OF memory */
-#if DEBUG
- prom_printf("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
-#endif
+ DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
/* On some systems, loadaddr may already be claimed, so try some
* other nearby addresses before giving up.
*/
- loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC32) ? KERNELADDR : e->e_entry;
+ loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC32 ||
+ e->e_entry == 0) ? KERNELADDR : e->e_entry;
for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
if (loadinfo->base != (void *)-1) break;
}
if (loadinfo->base == (void *)-1) {
- prom_printf("claim error, can't allocate kernel memory\n");
+ prom_printf("Claim error, can't allocate kernel memory\n");
return 0;
}
-#if DEBUG
- prom_printf("After ELF parsing, load base: 0x%08lx, mem_sz: 0x%08lx\n",
+ DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
loadinfo->base, loadinfo->memsize);
- prom_printf(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
+ DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
loadaddr, loadinfo->memsize);
-#endif
/* Load the program segments... */
p = ph;
/* Now, we skip to the image itself */
if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
- prom_printf ("seek error\n");
+ prom_printf ("Seek error\n");
prom_release(loadinfo->base, loadinfo->memsize);
return 0;
}
offset = p->p_vaddr - loadinfo->load_loc;
-#ifdef CONFIG_SPLASH_SCREEN
- if (fxReadImage(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
-#else /* CONFIG_SPLASH_SCREEN */
if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
-#endif /* CONFIG_SPLASH_SCREEN */
- prom_printf ("read failed\n");
- prom_release(loadinfo->base, loadinfo->memsize);
- return 0;
+ prom_printf ("Read failed\n");
+ prom_release(loadinfo->base, loadinfo->memsize);
+ return 0;
}
}
-#if 0 /* to make editor happy */
- }
-#endif
- (*(file->fs->close))(file);
-
free(ph);
/* Return success at loading the Elf32 kernel */
return 0;
}
-#if DEBUG
- prom_printf("Elf64 header:\n");
- prom_printf(" e.e_type = %d\n", (int)e->e_type);
- prom_printf(" e.e_machine = %d\n", (int)e->e_machine);
- prom_printf(" e.e_version = %d\n", (int)e->e_version);
- prom_printf(" e.e_entry = 0x%016lx\n", (long)e->e_entry);
- prom_printf(" e.e_phoff = 0x%016lx\n", (long)e->e_phoff);
- prom_printf(" e.e_shoff = 0x%016lx\n", (long)e->e_shoff);
- prom_printf(" e.e_flags = %d\n", (int)e->e_flags);
- prom_printf(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
- prom_printf(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
- prom_printf(" e.e_phnum = %d\n", (int)e->e_phnum);
-#endif
+ DEBUG_F("Elf64 header:\n");
+ DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
+ DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
+ DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
+ DEBUG_F(" e.e_entry = 0x%016lx\n", (long)e->e_entry);
+ DEBUG_F(" e.e_phoff = 0x%016lx\n", (long)e->e_phoff);
+ DEBUG_F(" e.e_shoff = 0x%016lx\n", (long)e->e_shoff);
+ DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
+ DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
+ DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
+ DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
loadinfo->entry = e->e_entry;
if (e->e_phnum > MAX_HEADERS) {
- prom_printf ("can only load kernels with one program header\n");
+ prom_printf ("Can only load kernels with one program header\n");
return 0;
}
ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
if (!ph) {
- prom_printf ("malloc error\n");
+ prom_printf ("Malloc error\n");
return 0;
}
/* Now, we read the section header */
if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
- prom_printf ("seek error\n");
+ prom_printf ("Seek error\n");
return 0;
}
if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) !=
sizeof(Elf64_Phdr) * e->e_phnum) {
- prom_printf ("read error\n");
+ prom_printf ("Read error\n");
return 0;
}
/* leave some room (1Mb) for boot infos */
loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
/* Claim OF memory */
-#if DEBUG
- prom_printf("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
-#endif
+ DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
/* On some systems, loadaddr may already be claimed, so try some
* other nearby addresses before giving up.
if (loadinfo->base != (void *)-1) break;
}
if (loadinfo->base == (void *)-1) {
- prom_printf("claim error, can't allocate kernel memory\n");
+ prom_printf("Claim error, can't allocate kernel memory\n");
return 0;
}
-#if DEBUG
- prom_printf("After ELF parsing, load base: 0x%08lx, mem_sz: 0x%08lx\n",
+ DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
loadinfo->base, loadinfo->memsize);
- prom_printf(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
+ DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
loadaddr, loadinfo->memsize);
-#endif
/* Load the program segments... */
p = ph;
/* Now, we skip to the image itself */
if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
- prom_printf ("seek error\n");
+ prom_printf ("Seek error\n");
prom_release(loadinfo->base, loadinfo->memsize);
return 0;
}
offset = p->p_vaddr - loadinfo->load_loc;
-#ifdef CONFIG_SPLASH_SCREEN
- if (fxReadImage(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
-#else /* CONFIG_SPLASH_SCREEN */
if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
-#endif /* CONFIG_SPLASH_SCREEN */
- prom_printf ("read failed\n");
+ prom_printf ("Read failed\n");
prom_release(loadinfo->base, loadinfo->memsize);
return 0;
}
}
-#if 0 /* to make editor happy */
- }
-#endif
- (*(file->fs->close))(file);
-
free(ph);
/* Return success at loading the Elf64 kernel */
/* Try Apple's mac-boot screen ihandle */
result = (int)call_prom_return("interpret", 1, 2,
"\" _screen-ihandle\" $find if execute else 0 then", &scrn);
-#if DEBUG
- prom_printf("trying to get screen ihandle, result: 0x%x, scrn: 0x%x\n", result, scrn);
-#endif
+ DEBUG_F("Trying to get screen ihandle, result: %d, scrn: %p\n", result, scrn);
+
if (scrn == 0 || scrn == PROM_INVALID_HANDLE) {
char type[32];
/* Hrm... check to see if stdout is a display */
scrn = call_prom ("instance-to-package", 1, 1, prom_stdout);
-#if DEBUG
- prom_printf("instance-to-package of stdout is: 0x%x\n", scrn);
-#endif
+ DEBUG_F("instance-to-package of stdout is: %p\n", scrn);
if (prom_getprop(scrn, "device_type", type, 32) > 0 && !strncmp(type, "display", 7)) {
-#if DEBUG
- prom_printf("got it ! stdout is a screen\n");
-#endif
+ DEBUG_F("got it ! stdout is a screen\n");
scrn = prom_stdout;
} else {
/* Else, we try to open the package */
scrn = (prom_handle)call_prom( "open", 1, 1, "screen" );
-#if DEBUG
- prom_printf("Open screen result: 0x%x\n", scrn);
-#endif
+ DEBUG_F("Open screen result: %p\n", scrn);
}
}
if (scrn == PROM_INVALID_HANDLE) {
- prom_printf("no screen device found !/n");
+ prom_printf("No screen device found !/n");
return;
}
for(i=0;i<16;i++) {
ansi_color_table[i].name);
}
prom_printf("\x1b[1;37m\x1b[2;40m");
-#endif
+#endif /* COLOR_TEST */
+
#if !DEBUG
prom_printf("\xc");
-#endif
+#endif /* !DEBUG */
+
#endif /* CONFIG_SET_COLORMAP */
}
setup_display();
prom_get_chosen("bootpath", bootdevice, sizeof(bootdevice));
-#if DEBUG
- prom_printf("/chosen/bootpath = %s\n", bootdevice);
-#endif
+ DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
if (bootdevice[0] == 0)
prom_get_options("boot-device", bootdevice, sizeof(bootdevice));
if (bootdevice[0] == 0) {
prom_printf("Couldn't determine boot device\n");
return -1;
}
- parse_device_path(bootdevice, &bootpath, &bootpartition);
-#if DEBUG
- prom_printf("after parse_device_path: device:%s, path: %s, partition: %d\n",
- bootdevice, bootpath ? bootpath : NULL, bootpartition);
-#endif
- if (bootpath) {
- if (!strncmp(bootpath, "\\\\", 2))
- bootpath[2] = 0;
- else {
- char *p, *last;
- p = last = bootpath;
- while(*p) {
- if (*p == '\\')
- last = p;
- p++;
- }
- if (p)
- *(last) = 0;
- else
- bootpath = NULL;
- if (bootpath && strlen(bootpath))
- strcat(bootpath, "\\");
- }
+
+ if (!parse_device_path(bootdevice, (_machine == _MACH_Pmac) ? "hd" : "disc",
+ -1, "", &boot)) {
+ prom_printf("%s: Unable to parse\n", bootdevice);
+ return -1;
}
-#if DEBUG
- prom_printf("after path fixup: device:%s, path: %s, partition: %d\n",
- bootdevice, bootpath ? bootpath : NULL, bootpartition);
-#endif
- useconf = load_config_file(bootdevice, bootpath, bootpartition);
+ DEBUG_F("After parse_device_path: dev=%s, part=%d, file=%s\n",
+ boot.dev, boot.part, boot.file);
+
+ if (strlen(boot.file)) {
+ if (!strncmp(boot.file, "\\\\", 2))
+ boot.file = "\\\\";
+ else {
+ char *p, *last;
+ p = last = boot.file;
+ while(*p) {
+ if (*p == '\\')
+ last = p;
+ p++;
+ }
+ if (p)
+ *(last) = 0;
+ else
+ boot.file = "";
+ if (strlen(boot.file))
+ strcat(boot.file, "\\");
+ }
+ }
+ DEBUG_F("After path fixup: dev=%s, part=%d, file=%s\n",
+ boot.dev, boot.part, boot.file);
+
+ useconf = load_config_file(boot.dev, boot.file, boot.part);
prom_printf("Welcome to yaboot version " VERSION "\n");
+ prom_printf("Enter \"help\" to get some basic usage information\n");
yaboot_text_ui();
prom_printf("Bye.\n");
return 0;
}
+/*
+ * Local variables:
+ * c-file-style: "K&R"
+ * c-basic-offset: 5
+ * End:
+ */
exit(0);
notelf:
- fprintf(stderr, "%s does not appear to be an ELF file\n", av[0]);
+ fprintf(stderr, "%s does not appear to be an ELF file\n", av[1]);
exit(1);
nospace:
fi
PRG="${0##*/}"
SIGINT="$PRG: Interrupt caught ... exiting"
-VERSION=1.3.3
+VERSION=1.3.4pre1
DEBUG=0
VERBOSE=0
TMP="${TMPDIR:-/tmp}"