From 8d5a42062f8b88eaea91434e53973ce9f55589d9 Mon Sep 17 00:00:00 2001 From: Ethan Benson Date: Mon, 25 Mar 2002 15:13:19 +0000 Subject: [PATCH] Commit yaboot 1.3.4-pre1 Commit yaboot 1.3.4-pre1. git-archimport-id: erbenson@alaska.net--public/yaboot--devel--1.3--patch-5 --- ChangeLog | 38 + Config | 30 + Makefile | 80 ++- THANKS | 1 + changelog | 24 + include/errors.h | 36 + include/file.h | 24 +- include/fs.h | 21 +- include/gui.h | 3 - include/prom.h | 9 + include/string.h | 2 +- include/video.h | 6 - include/xfs/xfs.h | 545 ++++++++++++++ include/yaboot.h | 3 +- lib/malloc.c | 6 +- second/cfg.c | 6 +- second/file.c | 162 +++-- second/fs.c | 31 +- second/fs_ext2.c | 61 +- second/fs_iso.c | 8 +- second/fs_of.c | 290 ++++---- second/fs_reiserfs.c | 1563 +++++++++++++++++++++-------------------- second/fs_xfs.c | 800 +++++++++++++++++++++ second/gui/colormap.c | 108 --- second/gui/effects.c | 95 --- second/gui/pcx.c | 31 - second/gui/video.c | 147 ---- second/partition.c | 4 +- second/prom.c | 46 +- second/yaboot.c | 578 +++++++-------- util/addnote.c | 2 +- ybin/ybin | 2 +- 32 files changed, 2989 insertions(+), 1773 deletions(-) create mode 100644 Config create mode 100644 include/errors.h delete mode 100644 include/gui.h delete mode 100644 include/video.h create mode 100644 include/xfs/xfs.h create mode 100644 second/fs_xfs.c delete mode 100644 second/gui/colormap.c delete mode 100644 second/gui/effects.c delete mode 100644 second/gui/pcx.c delete mode 100644 second/gui/video.c diff --git a/ChangeLog b/ChangeLog index e517c1e..1052750 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,44 @@ # tag: automatic-ChangeLog--erbenson@alaska.net--public/yaboot--devel--1.3 # +2002-03-25 15:13:19 GMT Ethan Benson 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 patch-4 Summary: diff --git a/Config b/Config new file mode 100644 index 0000000..0d03fa0 --- /dev/null +++ b/Config @@ -0,0 +1,30 @@ +# 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: diff --git a/Makefile b/Makefile index c9a55e2..4b2274e 100644 --- a/Makefile +++ b/Makefile @@ -1,22 +1,17 @@ -## 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 @@ -33,29 +28,33 @@ KERNELADDR = 0x01400000 # 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 @@ -65,43 +64,50 @@ LFLAGS = -Ttext $(TEXTADDR) -Bstatic # 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 @@ -110,10 +116,10 @@ mkofboot: 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 diff --git a/THANKS b/THANKS index 630a169..f81e094 100644 --- a/THANKS +++ b/THANKS @@ -2,6 +2,7 @@ In no particular order: * Daniel Jacobowitz for Debian packaging, advice and busybox help. * Benjamin Herrenschmidt for yaboot and great work on the kernel. + * Colin Walters for advice, help with XFS and general code auditing. * Charles Stevenson for adding color config support to yaboot. * Chris Emerson for the Forth code in ofboot. * iNOUE Koich! for advice and help [re]writing ofboot's Forth code. diff --git a/changelog b/changelog index 8166c51..b4aaafa 100644 --- a/changelog +++ b/changelog @@ -1,3 +1,27 @@ +2001-10-09 Ethan Benson + + * 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 * Version 1.3.3 diff --git a/include/errors.h b/include/errors.h new file mode 100644 index 0000000..c4950e5 --- /dev/null +++ b/include/errors.h @@ -0,0 +1,36 @@ +/* + * 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 diff --git a/include/file.h b/include/file.h index c68d84f..03c5c6f 100644 --- a/include/file.h +++ b/include/file.h @@ -31,18 +31,6 @@ struct boot_file_t; #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 @@ -73,9 +61,15 @@ struct boot_file_t { // 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, @@ -84,7 +78,7 @@ extern char *parse_device_path( char* of_device, char** file_spec, int* partition); - +#endif #endif diff --git a/include/fs.h b/include/fs.h index 3ec5928..647c37a 100644 --- a/include/fs.h +++ b/include/fs.h @@ -24,6 +24,8 @@ #include "partition.h" #include "file.h" +int fserrorno; + struct fs_t { const char* name; @@ -45,26 +47,33 @@ struct fs_t { 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 diff --git a/include/gui.h b/include/gui.h deleted file mode 100644 index c1aaec6..0000000 --- a/include/gui.h +++ /dev/null @@ -1,3 +0,0 @@ -extern void fxDisplaySplash(struct boot_fspec_t *filespec); -int fxReadImage(struct boot_file_t *file, unsigned int filesize, void *base); - diff --git a/include/prom.h b/include/prom.h index b217be4..546d082 100644 --- a/include/prom.h +++ b/include/prom.h @@ -62,9 +62,17 @@ int prom_getchar (); 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); @@ -87,6 +95,7 @@ void prom_setargs (char *args); void prom_exit (); void prom_abort (char *fmt, ...); +void prom_sleep (int seconds); int prom_interpret (char *forth); diff --git a/include/string.h b/include/string.h index 6d65773..4d2b3c3 100644 --- a/include/string.h +++ b/include/string.h @@ -19,7 +19,7 @@ extern size_t strspn(const char *,const char *); 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); diff --git a/include/video.h b/include/video.h deleted file mode 100644 index c5f61b8..0000000 --- a/include/video.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __VIDEO_H__ -#define __VIDEO_H__ - - - -#endif \ No newline at end of file diff --git a/include/xfs/xfs.h b/include/xfs/xfs.h new file mode 100644 index 0000000..51db098 --- /dev/null +++ b/include/xfs/xfs.h @@ -0,0 +1,545 @@ +/* + * 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 */ diff --git a/include/yaboot.h b/include/yaboot.h index d7a9277..99d60b7 100644 --- a/include/yaboot.h +++ b/include/yaboot.h @@ -7,7 +7,6 @@ struct boot_param_t { struct boot_fspec_t kernel; struct boot_fspec_t rd; struct boot_fspec_t sysmap; - struct boot_fspec_t splash; char* args; }; @@ -17,4 +16,4 @@ extern char bootdevice[]; extern char *bootpath; extern int bootpartition; -#endif \ No newline at end of file +#endif diff --git a/lib/malloc.c b/lib/malloc.c index 45f1409..4e3b248 100644 --- a/lib/malloc.c +++ b/lib/malloc.c @@ -101,10 +101,10 @@ void release (void *ptr) 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; } diff --git a/second/cfg.c b/second/cfg.c index ee90116..00414be 100644 --- a/second/cfg.c +++ b/second/cfg.c @@ -62,7 +62,6 @@ CONFIG cf_options[] = {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}}; @@ -88,7 +87,6 @@ CONFIG cf_image[] = {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}}; @@ -432,9 +430,7 @@ void cfg_print_images (void) 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) diff --git a/second/file.c b/second/file.c index 726f313..3aaef82 100644 --- a/second/file.c +++ b/second/file.c @@ -25,6 +25,7 @@ #include "string.h" #include "partition.h" #include "fs.h" +#include "errors.h" extern char bootdevice[1024]; @@ -33,6 +34,60 @@ 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) { @@ -43,30 +98,41 @@ 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 @@ -90,6 +156,8 @@ validate_fspec( struct boot_fspec_t* spec, return FILE_ERR_OK; } +#endif + static int file_block_open( struct boot_file_t* file, const char* dev_name, @@ -110,10 +178,8 @@ file_block_open( struct boot_file_t* file, 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) @@ -130,14 +196,14 @@ file_block_open( struct boot_file_t* file, /* 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 @@ -186,10 +252,10 @@ static struct fs_t fs_default = 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; @@ -201,6 +267,7 @@ int open_file( const struct boot_fspec_t* spec, /* 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); @@ -208,30 +275,30 @@ int open_file( const struct boot_fspec_t* spec, 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 for device\n"); - return FILE_ERR_NOTFOUND; + return FILE_ERR_BADDEV; } temps[result] = 0; if (!strcmp(temps, "block")) @@ -240,20 +307,23 @@ int open_file( const struct boot_fspec_t* spec, 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: + */ diff --git a/second/fs.c b/second/fs.c index b5ba2ca..1744f7d 100644 --- a/second/fs.c +++ b/second/fs.c @@ -20,17 +20,32 @@ #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 }; @@ -39,13 +54,13 @@ const struct fs_t *fs_of = &of_filesystem; /* needed by ISO9660 */ 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; } diff --git a/second/fs_ext2.c b/second/fs_ext2.c index e2a5070..af3d115 100644 --- a/second/fs_ext2.c +++ b/second/fs_ext2.c @@ -33,6 +33,7 @@ #include "string.h" #include "partition.h" #include "fs.h" +#include "errors.h" #define FAST_VERSION #define MAX_READ_RANGE 256 @@ -124,6 +125,7 @@ ext2_open( struct boot_file_t* file, const char* file_name) { int result = 0; + int error = FILE_ERR_NOTFOUND; static char buffer[1024]; int ofopened = 0; @@ -132,11 +134,13 @@ ext2_open( struct boot_file_t* file, 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; @@ -152,7 +156,7 @@ ext2_open( struct boot_file_t* file, 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); @@ -162,13 +166,13 @@ ext2_open( struct boot_file_t* file, 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; @@ -178,7 +182,7 @@ ext2_open( struct boot_file_t* file, 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 @@ -186,7 +190,7 @@ ext2_open( struct boot_file_t* file, DEBUG_F( "ext2fs_open error #%d while loading file %s\n", result, file_name); } - + error = FILE_ERR_BAD_FSYS; goto bail; } @@ -195,7 +199,7 @@ ext2_open( struct boot_file_t* file, if (!block_buffer) { DEBUG_F("ext2fs: can't alloc block buffer (%d bytes)\n", fs->blocksize * 2); - + error = FILE_IOERR; goto bail; } @@ -205,6 +209,12 @@ ext2_open( struct boot_file_t* file, 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; } @@ -213,7 +223,7 @@ ext2_open( struct boot_file_t* file, if (result) { DEBUG_F("ext2fs_follow_link error #%d while loading file %s\n", result, file_name); - + error = FILE_ERR_NOTFOUND; goto bail; } #endif @@ -223,7 +233,14 @@ ext2_open( struct boot_file_t* file, 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 */ @@ -242,8 +259,8 @@ bail: 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); @@ -420,10 +437,10 @@ ext2_read( struct boot_file_t* file, #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; @@ -447,7 +464,7 @@ ext2_read( struct boot_file_t* 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; @@ -456,7 +473,7 @@ ext2_read( struct boot_file_t* file, 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); @@ -507,7 +524,7 @@ ext2_seek( struct boot_file_t* file, unsigned int newpos) { if (!opened) - return FILE_ERR_NOTFOUND; + return FILE_CANT_SEEK; file->pos = newpos; return FILE_ERR_OK; @@ -517,7 +534,7 @@ static int ext2_close( struct boot_file_t* file) { if (!opened) - return FILE_ERR_NOTFOUND; + return FILE_IOERR; if (block_buffer) free(block_buffer); @@ -528,6 +545,7 @@ ext2_close( struct boot_file_t* file) fs = NULL; prom_close(file->of_device); + DEBUG_F("ext2_close called\n"); opened = 0; @@ -586,7 +604,7 @@ static errcode_t linux_read_blk (io_channel channel, unsigned long block, int co 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; @@ -601,4 +619,3 @@ static errcode_t linux_flush (io_channel channel) { return 0; } - diff --git a/second/fs_iso.c b/second/fs_iso.c index 9f52a3d..50479a9 100644 --- a/second/fs_iso.c +++ b/second/fs_iso.c @@ -24,7 +24,7 @@ #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, @@ -52,7 +52,7 @@ iso_open( struct boot_file_t* file, struct partition_t* part, const char* file_name) { - return FILE_ERR_NOTFOUND; + return FILE_ERR_BAD_FSYS; } static int @@ -60,14 +60,14 @@ iso_read( struct boot_file_t* file, 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 diff --git a/second/fs_of.c b/second/fs_of.c index abb006b..2dbc333 100644 --- a/second/fs_of.c +++ b/second/fs_of.c @@ -35,207 +35,203 @@ #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: + */ diff --git a/second/fs_reiserfs.c b/second/fs_reiserfs.c index f28680f..28f6d4e 100644 --- a/second/fs_reiserfs.c +++ b/second/fs_reiserfs.c @@ -26,24 +26,25 @@ #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 ); @@ -63,123 +64,128 @@ static int 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 @@ -189,76 +195,76 @@ journal_read( __u32 block, __u32 len, char *buffer ) 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 @@ -272,215 +278,222 @@ block_read( __u32 blockNr, __u32 start, __u32 len, char *buffer ) 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 *****************************/ @@ -510,43 +523,43 @@ reiserfs_read_super( void ) 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 @@ -555,88 +568,88 @@ read_tree_node( __u32 blockNr, __u16 depth ) 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 @@ -652,155 +665,155 @@ next_key( void ) 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; } @@ -814,212 +827,226 @@ reiserfs_read_data( char *buf, __u32 len ) 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: + */ diff --git a/second/fs_xfs.c b/second/fs_xfs.c new file mode 100644 index 0000000..866ceac --- /dev/null +++ b/second/fs_xfs.c @@ -0,0 +1,800 @@ +/* + * 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: + */ diff --git a/second/gui/colormap.c b/second/gui/colormap.c deleted file mode 100644 index 1317d46..0000000 --- a/second/gui/colormap.c +++ /dev/null @@ -1,108 +0,0 @@ -/* 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, -}; diff --git a/second/gui/effects.c b/second/gui/effects.c deleted file mode 100644 index afcd374..0000000 --- a/second/gui/effects.c +++ /dev/null @@ -1,95 +0,0 @@ -/* 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); -} diff --git a/second/gui/pcx.c b/second/gui/pcx.c deleted file mode 100644 index 0509777..0000000 --- a/second/gui/pcx.c +++ /dev/null @@ -1,31 +0,0 @@ -/* 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); - } -} diff --git a/second/gui/video.c b/second/gui/video.c deleted file mode 100644 index b3bd572..0000000 --- a/second/gui/video.c +++ /dev/null @@ -1,147 +0,0 @@ -#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 ); -} diff --git a/second/partition.c b/second/partition.c index aa04c86..39f23ca 100644 --- a/second/partition.c +++ b/second/partition.c @@ -223,7 +223,7 @@ partitions_lookup(const char *device) 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; } @@ -246,7 +246,7 @@ partitions_lookup(const char *device) 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; } diff --git a/second/prom.c b/second/prom.c index 153020d..cd12279 100644 --- a/second/prom.c +++ b/second/prom.c @@ -29,6 +29,7 @@ #include "types.h" #include "ctype.h" #include "asm/processor.h" +#include "errors.h" #define READ_BLOCKS_USE_READ 1 @@ -124,7 +125,7 @@ call_method_1 (char *method, prom_handle h, int nargs, ...) 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]; @@ -384,7 +385,7 @@ prom_puts (prom_handle file, char *s) 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); } @@ -392,7 +393,7 @@ prom_vfprintf (prom_handle file, char *fmt, va_list ap) 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); } @@ -415,6 +416,37 @@ prom_printf (char *fmt, ...) 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) { @@ -473,6 +505,14 @@ prom_abort (char *fmt, ...) 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) { diff --git a/second/yaboot.c b/second/yaboot.c index 5925d07..4bb67e2 100644 --- a/second/yaboot.c +++ b/second/yaboot.c @@ -40,6 +40,7 @@ sys #include "stdlib.h" #include "prom.h" #include "file.h" +#include "errors.h" #include "cfg.h" #include "cmdline.h" #include "yaboot.h" @@ -49,10 +50,6 @@ sys #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 */ @@ -107,9 +104,10 @@ static void setup_display(void); 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 @@ -191,25 +189,22 @@ yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5) /* 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("/"); @@ -225,9 +220,8 @@ yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5) } } -#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(); @@ -235,12 +229,9 @@ yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5) /* 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(); @@ -324,9 +315,7 @@ load_config_file(char *device, char* path, int partition) 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"); @@ -338,9 +327,7 @@ load_config_file(char *device, char* path, int partition) #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); @@ -348,9 +335,7 @@ load_config_file(char *device, char* path, int partition) } 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); @@ -361,7 +346,7 @@ load_config_file(char *device, char* path, int partition) prom_interpret(temp); #if !DEBUG prom_printf("\xc"); -#endif +#endif /* !DEBUG */ } if (fgcolor >= 0) { char temp[64]; @@ -498,7 +483,7 @@ make_params(char *label, char *params) void check_password(char *str) { - int i, end; + int i; for (i = 0; i < 3; i++) { prom_printf ("\n%sassword: ", str); @@ -512,16 +497,15 @@ void check_password(char *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"); } @@ -541,9 +525,6 @@ int get_params(struct boot_param_t* params) 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)); @@ -551,8 +532,7 @@ int get_params(struct boot_param_t* params) params->kernel.part = -1; params->rd.part = -1; params->sysmap.part = -1; - params->splash.part = -1; - defpart = bootpartition; + defpart = boot.part; cmdinit(); @@ -563,8 +543,7 @@ int get_params(struct boot_param_t* params) 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"); @@ -627,7 +606,7 @@ int get_params(struct boot_param_t* params) imagename = cfg_get_default(); label = 0; - defdevice = bootdevice; + defdevice = boot.dev; if (useconf) { defdevice = cfg_get_strg(0, "device"); @@ -647,7 +626,7 @@ int get_params(struct boot_param_t* params) 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); @@ -666,6 +645,23 @@ int get_params(struct boot_param_t* params) } } + 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 to boot it.\n\n" + "To boot any other label simply type its name and press .\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"); @@ -693,52 +689,36 @@ int get_params(struct boot_param_t* params) 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; } @@ -779,121 +759,139 @@ yaboot_text_ui(void) 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); @@ -905,20 +903,19 @@ yaboot_text_ui(void) 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"); @@ -926,17 +923,11 @@ yaboot_text_ui(void) } } -#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 @@ -952,14 +943,8 @@ yaboot_text_ui(void) * 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); @@ -989,26 +974,21 @@ yaboot_text_ui(void) /* 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 */ } } @@ -1027,30 +1007,28 @@ load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo) 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; } @@ -1095,29 +1073,26 @@ load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo) /* 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; @@ -1128,27 +1103,18 @@ load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo) /* 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 */ @@ -1170,41 +1136,39 @@ load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo) 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; } @@ -1238,9 +1202,7 @@ load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo) /* 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. @@ -1251,16 +1213,14 @@ load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo) 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; @@ -1271,27 +1231,18 @@ load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo) /* 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 */ @@ -1356,32 +1307,25 @@ setup_display(void) /* 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++) { @@ -1403,10 +1347,12 @@ setup_display(void) 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 */ } @@ -1417,49 +1363,57 @@ yaboot_main(void) 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: + */ diff --git a/util/addnote.c b/util/addnote.c index 4088c32..74c8efc 100644 --- a/util/addnote.c +++ b/util/addnote.c @@ -153,7 +153,7 @@ main(int ac, char **av) 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: diff --git a/ybin/ybin b/ybin/ybin index 976423c..8b8f402 100755 --- a/ybin/ybin +++ b/ybin/ybin @@ -28,7 +28,7 @@ if [ -n "$PATH_PREFIX" ] ; then fi PRG="${0##*/}" SIGINT="$PRG: Interrupt caught ... exiting" -VERSION=1.3.3 +VERSION=1.3.4pre1 DEBUG=0 VERBOSE=0 TMP="${TMPDIR:-/tmp}" -- 2.39.2