Submitted By: William Harrington Date: 2012-09-01 Initial Package Version: 1.4.14 Upstream Status: Unknown Origin: git clone https://kernel.googlesource.com/pub/scm/linux/kernel/git/davem/silo Description: Fixes for current silo.1.4.14 not yet released. diff -Naur silo-1.4.14.orig/Rules.make silo-1.4.14/Rules.make --- silo-1.4.14.orig/Rules.make 2008-06-12 16:39:12.000000000 +0000 +++ silo-1.4.14/Rules.make 2012-09-01 19:14:27.000000000 +0000 @@ -1,4 +1,4 @@ -VERSION=1.4.14 +VERSION=1.4.14_git20120901 IMGVERSION=0.99 SHELL=/bin/bash RM=rm -f @@ -18,8 +18,8 @@ > /dev/null 2>&1; then echo "y"; else echo "n"; fi;) CFLAGS = -Os -Wall -I. -I../include -fomit-frame-pointer \ - -fno-strict-aliasing -DSMALL_RELOC=$(SMALL_RELOC) \ - -DLARGE_RELOC=$(LARGE_RELOC) + -fno-strict-aliasing -U_FORTIFY_SOURCE \ + -DSMALL_RELOC=$(SMALL_RELOC) -DLARGE_RELOC=$(LARGE_RELOC) ifeq ($(call cc-option-yn, -fno-stack-protector),y) CFLAGS += -fno-stack-protector diff -Naur silo-1.4.14.orig/common/.gitignore silo-1.4.14/common/.gitignore --- silo-1.4.14.orig/common/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ silo-1.4.14/common/.gitignore 2012-09-01 19:05:11.000000000 +0000 @@ -0,0 +1,4 @@ +# +# Generated files +# +bin2h diff -Naur silo-1.4.14.orig/common/divdi3.S silo-1.4.14/common/divdi3.S --- silo-1.4.14.orig/common/divdi3.S 2008-06-12 16:39:12.000000000 +0000 +++ silo-1.4.14/common/divdi3.S 2012-09-01 19:06:01.000000000 +0000 @@ -20,6 +20,8 @@ .data .align 8 .globl __clz_tab + .register %g2,#scratch + .register %g3,#scratch __clz_tab: .byte 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 .byte 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 diff -Naur silo-1.4.14.orig/common/malloc.c silo-1.4.14/common/malloc.c --- silo-1.4.14.orig/common/malloc.c 2008-06-12 16:39:12.000000000 +0000 +++ silo-1.4.14/common/malloc.c 2012-09-01 19:05:11.000000000 +0000 @@ -18,6 +18,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include + #ifndef MALLOC_BASE extern unsigned long _start; static char *malloc_ptr = ((char *)&_start) + 0x30000; @@ -27,6 +29,12 @@ static char *last_alloc = 0; +static char *align_ptr_to(char *ptr, unsigned long align) +{ + return (char *) ((((unsigned long) ptr) + (align - 1UL)) & + ~(align - 1UL)); +} + void *malloc (int size) { char *caddr; @@ -34,10 +42,51 @@ caddr = malloc_ptr; malloc_ptr += size; last_alloc = caddr; - malloc_ptr = (char *) ((((unsigned long) malloc_ptr) + 7) & (~7)); + malloc_ptr = align_ptr_to(malloc_ptr, 8UL); return caddr; } +void *calloc (int nmemb, int memb_size) +{ + char *ret; + int size; + + if (!nmemb || !memb_size) + return (void *) 0; + + size = nmemb * memb_size; + ret = malloc(size); + + if (ret) + memset(ret, 0, size); + + return ret; +} + +int posix_memalign(void **memptr, unsigned long alignment, unsigned long size) +{ + char *caddr; + + if (alignment & (alignment - 1UL)) + return -1; + if (alignment & (sizeof(void *) - 1UL)) + return -1; + + if (size == 0) { + *memptr = (void *) 0; + return 0; + } + + caddr = align_ptr_to(malloc_ptr, alignment); + malloc_ptr = (caddr + size); + last_alloc = caddr; + malloc_ptr = align_ptr_to(malloc_ptr, 8UL); + + *memptr = caddr; + + return 0; +} + void free (void *m) { if (m == last_alloc) diff -Naur silo-1.4.14.orig/common/printf.c silo-1.4.14/common/printf.c --- silo-1.4.14.orig/common/printf.c 2008-06-12 16:39:12.000000000 +0000 +++ silo-1.4.14/common/printf.c 2012-09-01 19:05:11.000000000 +0000 @@ -21,6 +21,7 @@ USA. */ #include "promlib.h" +#include /* * This part is rewritten by Igor Timkin . Than I @@ -147,3 +148,91 @@ vprintf (fmt, x1); va_end (x1); } + +static int sprintn (char *str, long long n, int b) +{ + static char prbuf[33]; + register char *cp; + int count = 0; + + if (b == 10 && n < 0) { + memset (str + count, '-', 1); + count++; + n = -n; + } + cp = prbuf; + do + *cp++ = "0123456789ABCDEF"[(unsigned int) (((unsigned long)n) % b)]; + while ((n = ((unsigned long long)n) / b & 0x0FFFFFFFFFFFFFFFULL)); + do { + memset (str + count, *--cp, 1); + count++; + } while (cp > prbuf); + + return count; +} + +int vsprintf (char *str, char *fmt, va_list adx) +{ + register int c; + char *s; + int count = 0; + + for (;;) { + while ((c = *fmt++) != '%') { + memset (str + count, c, 1); + if (c == '\0') { + return count; + } + } + c = *fmt++; + if (c == 'd' || c == 'o' || c == 'x' || c == 'X') { + count += sprintn (str + count, (long long) va_arg (adx, unsigned), + c == 'o' ? 8 : (c == 'd' ? 10 : 16)); + } else if (c == 'c') { + memset (str + count, va_arg (adx, unsigned), 1); + count++; + } else if (c == 's') { + if ((s = va_arg (adx, char *)) == NULL) + s = (char *)"(null)"; + while ((c = *s++)) { + memset (str + count, c, 1); + count++; + } + } else if (c == 'l' || c == 'O') { + count += sprintn (str + count, (long long) va_arg (adx, long), c == 'l' ? 10 : 8); + } else if (c == 'L') { + int hex = 0; + if (*fmt == 'x') { + fmt++; + hex = 1; + } + count += sprintn (str + count, (long long) va_arg (adx, long long), hex ? 16 : 10); + } else { + /* This is basically what libc's printf does */ + memset (str + count, '%', 1); + count++; + memset (str + count, c, 1); + count++; + } + } + + return count; +} + +/* + * Scaled down version of C Library sprintf. + * Only %c %s %d (==%u) %o %x %X %l %O are recognized. + */ + +int sprintf (char *s, char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = vsprintf (s, format, arg); + va_end (arg); + + return done; +} diff -Naur silo-1.4.14.orig/common/udivdi3.S silo-1.4.14/common/udivdi3.S --- silo-1.4.14.orig/common/udivdi3.S 2008-06-12 16:39:12.000000000 +0000 +++ silo-1.4.14/common/udivdi3.S 2012-09-01 19:09:16.000000000 +0000 @@ -20,6 +20,8 @@ .text .align 4 .globl __udivdi3 + .register %g2,#scratch + .register %g3,#scratch __udivdi3: save %sp,-104,%sp mov %i3,%o3 diff -Naur silo-1.4.14.orig/first/.gitignore silo-1.4.14/first/.gitignore --- silo-1.4.14.orig/first/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ silo-1.4.14/first/.gitignore 2012-09-01 19:05:11.000000000 +0000 @@ -0,0 +1,16 @@ +# +# Generated files +# +fd +fd.b +fd.h +first +first.b +first.h +generic +generic.b +generic.h +ieee32.b +ultra +ultra.b +ultra.h diff -Naur silo-1.4.14.orig/first-isofs/.gitignore silo-1.4.14/first-isofs/.gitignore --- silo-1.4.14.orig/first-isofs/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ silo-1.4.14/first-isofs/.gitignore 2012-09-01 19:05:11.000000000 +0000 @@ -0,0 +1,5 @@ +# +# Generated files +# +isofs +isofs.b diff -Naur silo-1.4.14.orig/include/ext2fs/ext2fs.h silo-1.4.14/include/ext2fs/ext2fs.h --- silo-1.4.14.orig/include/ext2fs/ext2fs.h 2008-06-12 16:39:12.000000000 +0000 +++ silo-1.4.14/include/ext2fs/ext2fs.h 2012-09-01 19:05:11.000000000 +0000 @@ -39,7 +39,7 @@ */ #define EXT2_LIB_CURRENT_REV 0 -#ifdef HAVE_SYS_TYPES_H +#if defined(HAVE_SYS_TYPES_H) #include #endif diff -Naur silo-1.4.14.orig/include/silo.h silo-1.4.14/include/silo.h --- silo-1.4.14.orig/include/silo.h 2008-06-12 16:39:12.000000000 +0000 +++ silo-1.4.14/include/silo.h 2012-09-01 19:05:11.000000000 +0000 @@ -87,6 +87,8 @@ void silo_disk_close(void); /* printf.c */ int vprintf (char *, va_list); +int vsprintf (char *str, char *fmt, va_list adx); +int sprintf (char *s, char *format, ...); int putchar (int); /* malloc.c */ void *malloc (int); @@ -123,6 +125,7 @@ int decompress (char *, char *, unsigned char (*)(void), void (*)(void)); /* main.c */ extern enum arch architecture; +extern int sun4v_cpu; /* timer.c */ int init_timer (); void close_timer (); diff -Naur silo-1.4.14.orig/include/stringops.h silo-1.4.14/include/stringops.h --- silo-1.4.14.orig/include/stringops.h 2008-06-12 16:39:12.000000000 +0000 +++ silo-1.4.14/include/stringops.h 2012-09-01 19:05:11.000000000 +0000 @@ -2,14 +2,13 @@ #define __STRINGOPS_H #include +#include /* common */ #ifndef __SIZE_TYPE__ #define __SIZE_TYPE__ long unsigned int #endif -#ifndef _LINUX_TYPES_H typedef __SIZE_TYPE__ size_t; -#endif /* stringops1.c */ char *strcpy(char *, const char *); diff -Naur silo-1.4.14.orig/second/.gitignore silo-1.4.14/second/.gitignore --- silo-1.4.14.orig/second/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ silo-1.4.14/second/.gitignore 2012-09-01 19:05:11.000000000 +0000 @@ -0,0 +1,12 @@ +# +# Generated files +# +second +second.b +second.b2 +second2 +silotftp +silotftp.b +silotftp.b2 +silotftp2 +util diff -Naur silo-1.4.14.orig/second/Makefile silo-1.4.14/second/Makefile --- silo-1.4.14.orig/second/Makefile 2008-06-12 16:39:12.000000000 +0000 +++ silo-1.4.14/second/Makefile 2012-09-01 19:05:11.000000000 +0000 @@ -58,13 +58,13 @@ $(AR) rc $@ $(FS_OBJS) second: $(OBJS) mark.o - $(LD) $(LDFLAGS_SMALL) -Bstatic -o second $(OBJS) -lext2fs mark.o - $(LD) $(LDFLAGS_LARGE) -Bstatic -o second2 $(OBJS) -lext2fs mark.o + $(LD) $(LDFLAGS_SMALL) -Bstatic -o second $(OBJS) mark.o `$(CC) -print-libgcc-file-name` + $(LD) $(LDFLAGS_LARGE) -Bstatic -o second2 $(OBJS) mark.o `$(CC) -print-libgcc-file-name` $(NM) second | grep -v '*ABS*' | sort > second.map silotftp: $(OBJSNET) mark.o - $(LD) $(LDFLAGS_SMALL) -Bstatic -o silotftp $(OBJSNET) -lext2fs mark.o - $(LD) $(LDFLAGS_LARGE) -Bstatic -o silotftp2 $(OBJSNET) -lext2fs mark.o + $(LD) $(LDFLAGS_SMALL) -Bstatic -o silotftp $(OBJSNET) mark.o `$(CC) -print-libgcc-file-name` + $(LD) $(LDFLAGS_LARGE) -Bstatic -o silotftp2 $(OBJSNET) mark.o `$(CC) -print-libgcc-file-name` $(NM) silotftp | grep -v '*ABS*' | sort > silotftp.map second.l: second diff -Naur silo-1.4.14.orig/second/file.c silo-1.4.14/second/file.c --- silo-1.4.14.orig/second/file.c 2008-06-12 16:39:12.000000000 +0000 +++ silo-1.4.14/second/file.c 2012-09-01 19:05:11.000000000 +0000 @@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include #include #include #include diff -Naur silo-1.4.14.orig/second/fs/ext2.c silo-1.4.14/second/fs/ext2.c --- silo-1.4.14.orig/second/fs/ext2.c 2008-06-12 16:39:12.000000000 +0000 +++ silo-1.4.14/second/fs/ext2.c 2012-09-01 19:05:11.000000000 +0000 @@ -3,6 +3,7 @@ Copyright (C) 1996 Maurizio Plaza 1996,1997,1999 Jakub Jelinek 2001 Ben Collins + 2012 David S. Miller 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 @@ -27,118 +28,654 @@ static ino_t inode = 0; struct fs_ops ext2_fs_ops; -void com_err (const char *a, long i, const char *fmt,...) +#define EXT2_SUPER_MAGIC 0xEF53 + +static __u32 ext2_to_cpu_32(__u32 v) { - printf ((char *) fmt); + const __u8 *p = (const __u8 *) &v; + + return ((__u32)p[3] << 24 | + (__u32)p[2] << 16 | + (__u32)p[1] << 8 | + (__u32)p[0]); } -static void ext2fs_error (int errcode) +static __u16 ext2_to_cpu_16(__u16 v) { -#if 0 - int i; - for (i = 0; i < sizeof (ext2errors) / sizeof (ext2errors[0]); i++) - if (ext2errors[i].errnum == errcode) { - printf ("%s", ext2errors [i].desc); - return; - } -#endif - printf ("Unknown ext2 error: %d", errcode); + const __u8 *p = (const __u8 *) &v; + + return ((__u16)p[1] << 8) | ((__u16)p[0]); } -static int open_ext2 (char *device) +struct silo_ext2_state { + struct ext2_super_block *super; + + void *scratch_block[4]; + __u32 scratch_block_blk[4]; + + __u32 inode_size; + __u32 block_size; + __u32 addr_per_block; + __u32 addr_per_block_bits; + __u32 desc_per_block; + __u32 desc_per_block_bits; +}; +static struct silo_ext2_state *sstate; + +static __u32 ext2_inode_size(struct silo_ext2_state *s) { - int retval; + __u32 rev = ext2_to_cpu_32(s->super->s_rev_level); - retval = ext2fs_open (device, EXT2_FLAG_DIRTY, 0, 0, silo_io_manager, &fs); - if (retval == EXT2_ET_BAD_MAGIC) - return 0; - if (retval) { - printf ("\n"); - ext2fs_error (retval); - printf ("\n"); - return 0; - } - root = EXT2_ROOT_INO; - return 1; + if (rev == 0) + return 128; + + return ext2_to_cpu_16(s->super->s_inode_size); } -static int dump_block_ext2 (ext2_filsys fs, blk_t *blocknr, - int blockcnt, void *private) +static __u32 ext2_block_size(struct silo_ext2_state *s) { - return dump_block(blocknr, blockcnt); + __u32 x = ext2_to_cpu_32(s->super->s_log_block_size); + + x += 1; + + return ((__u32) 1 << x) * 512; } -static int dump_ext2 (void) +static void read_scratch_block(struct silo_ext2_state *s, __u32 block, int N) { - if (ext2fs_block_iterate (fs, inode, 0, 0, dump_block_ext2, 0)) + if (s->scratch_block_blk[N] == block) + return; + io_channel_read_blk(fs->io, block, 1, s->scratch_block[N]); + s->scratch_block_blk[N] = block; +} + +static void read_data(struct silo_ext2_state *s, __u32 block, __u32 off, __u32 len, void *buf) +{ + read_scratch_block(s, block, 0); + memcpy(buf, s->scratch_block[0] + off, len); +} + +static int has_extents(struct ext2_inode *ip) +{ + if (ext2_to_cpu_32(ip->i_flags) & 0x80000) + return 1; return 0; +} + +#define EXT4_EXT_MAGIC 0xf30a + +struct ext4_extent_header { + __u16 eh_magic; + __u16 eh_entries; + __u16 eh_max; + __u16 eh_depth; + __u32 eh_generation; +}; + +struct ext4_extent_idx { + __u32 ei_block; + __u32 ei_leaf_lo; + __u16 ei_leaf_hi; + __u16 ei_unused; +}; + +struct ext4_extent { + __u32 ee_block; + __u16 ee_len; + __u16 ee_start_hi; + __u32 ee_start_lo; +}; + +static struct ext4_extent_header *search_leaf(struct silo_ext2_state *s, + struct ext2_inode *ip, + unsigned long long file_block) +{ + struct ext4_extent_header *ehp; + + ehp = (struct ext4_extent_header *) &ip->i_block[0]; + for (;;) { + unsigned long long ext_block, hi, lo; + struct ext4_extent_idx *idxp; + int i; + + idxp = (struct ext4_extent_idx *) (ehp + 1); + + if (ext2_to_cpu_16(ehp->eh_magic) != EXT4_EXT_MAGIC) + return (struct ext4_extent_header *) 0; + + if (ehp->eh_depth == ext2_to_cpu_16(0)) + return ehp; + + for (i = 0; i < ext2_to_cpu_16(ehp->eh_entries); i++, idxp++) + if (file_block < ext2_to_cpu_32(idxp->ei_block)) + break; + + if (i == 0) + return (struct ext4_extent_header *) 0; + + idxp -= 1; + + hi = ((unsigned long long)ext2_to_cpu_16(idxp->ei_leaf_hi)) << 32; + lo = ext2_to_cpu_32(idxp->ei_leaf_lo); + ext_block = hi | lo; + + read_scratch_block(s, ext_block, 0); + ehp = (struct ext4_extent_header *) s->scratch_block[0]; + } +} + +#define BLOCK_MAP_ERROR (~0ULL) + +static int block_to_path(struct silo_ext2_state *s, struct ext2_inode *ip, + int offsets[4], long file_block) +{ + int ptrs_bits = s->addr_per_block_bits; + int ptrs = s->addr_per_block; + const long direct_blocks = EXT2_NDIR_BLOCKS, + indirect_blocks = ptrs, + double_blocks = (1 << (ptrs_bits * 2)); + int n = 0; + + if (file_block < 0) { + printf("EXT2: Illegal file block %ld\n", file_block); + } else if (file_block < direct_blocks) { + offsets[n++] = file_block; + } else if ((file_block -= direct_blocks) < indirect_blocks) { + offsets[n++] = EXT2_IND_BLOCK; + offsets[n++] = file_block; + } else if ((file_block -= indirect_blocks) < double_blocks) { + offsets[n++] = EXT2_DIND_BLOCK; + offsets[n++] = file_block >> ptrs_bits; + offsets[n++] = file_block & (ptrs - 1); + } else if (((file_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) { + offsets[n++] = EXT2_TIND_BLOCK; + offsets[n++] = file_block >> (ptrs_bits * 2); + offsets[n++] = (file_block >> ptrs_bits) & (ptrs - 1); + offsets[n++] = file_block & (ptrs - 1); + } else { + printf("EXT2: File block %ld is too big\n", file_block); + } + + return n; +} + +static unsigned long long resolve_path(struct silo_ext2_state *s, + struct ext2_inode *ip, + int *offsets, int depth) +{ + __u32 *p = ip->i_block + *offsets; + + while (--depth) { + __u32 block = ext2_to_cpu_32(*p); + + read_scratch_block(s, block, depth); + p = (__u32 *) s->scratch_block[depth] + *++offsets; + } + + return ext2_to_cpu_32(*p); +} + +static unsigned long long resolve_extent(struct silo_ext2_state *s, + struct ext4_extent_header *ehp, + unsigned long long file_block) +{ + unsigned long long hi, lo; + struct ext4_extent *ep; + int i; + + ep = (struct ext4_extent *) (ehp + 1); + + for (i = 0; i < ext2_to_cpu_16(ehp->eh_entries); i++, ep++) + if (file_block < ext2_to_cpu_32(ep->ee_block)) + break; + + if (i == 0) + return BLOCK_MAP_ERROR; + + ep -= 1; + file_block -= ext2_to_cpu_32(ep->ee_block); + if (file_block >= ext2_to_cpu_16(ep->ee_len)) + return BLOCK_MAP_ERROR; - return dump_finish (); + hi = ((unsigned long long)ext2_to_cpu_16(ep->ee_start_hi)) << 32; + lo = ext2_to_cpu_32(ep->ee_start_lo); + + return (hi | lo) + file_block; } -static int ls_ext2_proc(struct ext2_dir_entry *dirent, int offset, - int blocksize, char *buf, void *private) +static unsigned long long file_to_disk_block(struct silo_ext2_state *s, + struct ext2_inode *ip, + unsigned long long file_block) { - struct ext2_inode ino; - int sl = 0, name_len = dirent->name_len & 0xFF; - char name[256], symlink[256]; + if (has_extents(ip)) { + struct ext4_extent_header *ehp = search_leaf(s, ip, file_block); - strncpy(name, dirent->name, name_len); - name[name_len] = 0; + if (ehp) + return resolve_extent(s, ehp, file_block); - if (ext2fs_read_inode(fs, dirent->inode, &ino)) - strcpy (name, "--- error ---"); + printf("EXT2: Extent leaf search for block %d failed\n", + (int) file_block); - if (LINUX_S_ISLNK (ino.i_mode)) { - sl = 1; - if (ext2fs_inode_data_blocks(fs, &ino)) { - if (io_channel_read_blk(fs->io, ino.i_block[0], 1, symlink)) - ino.i_size = 0; + return BLOCK_MAP_ERROR; } else { - strncpy (symlink, (char *)&(ino.i_block[0]),ino.i_size); + int depth, offsets[4]; + + depth = block_to_path(s, ip, offsets, file_block); + if (depth) + return resolve_path(s, ip, offsets, depth); + + printf("EXT2: block --> path on block %d failed\n", + (int) file_block); + + return BLOCK_MAP_ERROR; + } +} + +static void read_file(struct silo_ext2_state *s, struct ext2_inode *ip, + __u32 off, __u32 len, void *buf) +{ + unsigned long long disk_block; + + disk_block = file_to_disk_block(s, ip, off / s->block_size); + + read_scratch_block(s, disk_block, 0); + memcpy(buf, s->scratch_block[0] + (off % s->block_size), len); +} + +static void read_group(struct silo_ext2_state *s, __u32 grp_no, + struct ext2_group_desc *grp) +{ + __u32 first = ext2_to_cpu_32(s->super->s_first_data_block); + __u32 blk, offset; + + blk = first + 1 + (grp_no >> s->desc_per_block_bits); + offset = (grp_no & (s->desc_per_block - 1)) * sizeof(*grp); + + read_data(s, blk, offset, sizeof(*grp), grp); +} + +static void read_inode(struct silo_ext2_state *s, __u32 ino, struct ext2_inode *ip) +{ + __u32 grp_no, blk_no, inode_in_block, ipg, ipb; + struct ext2_super_block *sb = s->super; + struct ext2_group_desc gd; + + ipg = ext2_to_cpu_32(sb->s_inodes_per_group); + + grp_no = (ino - 1) / ipg; + read_group(s, grp_no, &gd); + + blk_no = (ino - 1) % ipg; + inode_in_block = blk_no; + + ipb = s->block_size / s->inode_size; + blk_no /= ipb; + inode_in_block %= ipb; + + read_data(s, + ext2_to_cpu_32(gd.bg_inode_table) + blk_no, + inode_in_block * s->inode_size, + sizeof(struct ext2_inode), ip); +} + +static int calc_ilog2(__u32 n) +{ + int i = 0; + + while ((n >>= 1) != 0) + i++; + + return i; +} + +static int open_ext2(char *device) +{ + struct silo_ext2_state *s = malloc(sizeof(*s)); + struct ext2_super_block *sb; + int err, i; + + if (!s) { + printf("Cannot allocate silo_ext2_state\n"); + return 0; + } + memset(s, 0, sizeof(*s)); + + fs = malloc(sizeof(*fs)); + if (!fs) { + printf("Cannot allocate ext2_filsys\n"); + goto out_free_s; + } + memset(fs, 0, sizeof(*fs)); + err = silo_io_manager->open(device, 0, &fs->io); + if (err) { + printf("I/O manager open failed (err=%d)\n", err); + goto out_free_fs; + } + fs->io->app_data = fs; + + sb = s->super = malloc(1024); + if (!sb) { + printf("Cannot allocate ext2 super block\n"); + goto out_free_fs; + } + + io_channel_set_blksize(fs->io, 1024); + err = io_channel_read_blk(fs->io, 1, -1024, sb); + + if (ext2_to_cpu_16(sb->s_magic) != EXT2_SUPER_MAGIC) { + printf("EXT2 superblock magic is wrong\n"); + goto out_free_super; + } + + s->inode_size = ext2_inode_size(s); + s->block_size = ext2_block_size(s); + + io_channel_set_blksize(fs->io, s->block_size); + + s->addr_per_block = s->block_size / sizeof(__u32); + s->addr_per_block_bits = calc_ilog2(s->addr_per_block); + s->desc_per_block = s->block_size / sizeof(struct ext2_group_desc); + s->desc_per_block_bits = calc_ilog2(s->desc_per_block); + + s->scratch_block[0] = malloc(s->block_size * 4); + if (!s->scratch_block[0]) { + printf("Cannot allocate ext2 scratch blocks\n"); + goto out_free_super; + } + for (i = 1; i < 4; i++) + s->scratch_block[i] = + s->scratch_block[i - 1] + s->block_size; + for (i = 0; i < 4; i++) + s->scratch_block_blk[i] = ~(__u32)0; + + root = EXT2_ROOT_INO; + + sstate = s; + + return 1; + +out_free_super: + free(s->super); + +out_free_fs: + free(fs); + fs = NULL; + +out_free_s: + free(s); + return 0; +} + +void close_ext2 (void) +{ + struct silo_ext2_state *s = sstate; + + if (s) { + free(s->scratch_block[0]); + free(s->super); + free(s); + + sstate = (struct silo_ext2_state *) 0; } - symlink[ino.i_size] = 0; - } +} + +static int dump_ext2 (void) +{ + struct silo_ext2_state *s = sstate; + struct ext2_inode ei; + long file_offset; + int sz, blk_sz; + int blk_cnt; + + read_inode(s, inode, &ei); + + sz = ext2_to_cpu_32(ei.i_size); + blk_sz = s->block_size; + + blk_cnt = 0; + for (file_offset = 0; file_offset < sz; file_offset += blk_sz) { + blk_t disk_block; + + disk_block = file_to_disk_block(s, &ei, + file_offset / blk_sz); + if (disk_block == BLOCK_MAP_ERROR) + return 0; + + if (disk_block) + dump_block(&disk_block, blk_cnt); + + blk_cnt++; + } + + return dump_finish (); +} + +static char *read_symlink(struct silo_ext2_state *s, struct ext2_inode *ip, char *namebuf) +{ + __u32 isize = ext2_to_cpu_32(ip->i_size); + + if (isize <= 60) + return (char *) &ip->i_block[0]; + + read_data(s, ext2_to_cpu_32(ip->i_block[0]), 0, isize, namebuf); + + return namebuf; +} + +static int is_symlink(__u16 mode) +{ + if ((mode & 0xf000) == 0xa000) + return 1; + return 0; +} + +typedef int (*dir_callback_t)(struct silo_ext2_state *, struct ext2_dir_entry_2 *, void *); + +static int ls_callback(struct silo_ext2_state *s, struct ext2_dir_entry_2 *dirent, void *priv_data) +{ + struct ext2_inode e_ino; + char *sym = (char *) 0; + char symlink_buf[256]; + + read_inode(s, ext2_to_cpu_32(dirent->inode), &e_ino); + + if (is_symlink(ext2_to_cpu_16(e_ino.i_mode))) + sym = read_symlink(s, &e_ino, symlink_buf); + + register_silo_inode(ext2_to_cpu_32(e_ino.i_mtime), + ext2_to_cpu_32(e_ino.i_size), + ext2_to_cpu_16(e_ino.i_mode), + ext2_to_cpu_16(e_ino.i_uid), + ext2_to_cpu_16(e_ino.i_gid), + dirent->name, sym); + return 0; +} + +static void iterate_dir(struct silo_ext2_state *s, __u32 ino, dir_callback_t cb, void *cb_arg) +{ + struct ext2_dir_entry_2 e; + struct ext2_inode ei; + __u32 off, size; - register_silo_inode(ino.i_mtime, ino.i_size, ino.i_mode, ino.i_uid, - ino.i_gid, name, sl ? symlink : NULL); + read_inode(s, ino, &ei); + size = ext2_to_cpu_32(ei.i_size); - return 0; + for (off = 0; off < size; ) { + read_file(s, &ei, off, 8, &e); + + if (ext2_to_cpu_16(e.rec_len) == 0) + break; + + if (ext2_to_cpu_32(e.inode) == 0 || + e.name_len == 0) { + off += ext2_to_cpu_16(e.rec_len); + continue; + } + + read_file(s, &ei, off + 8, e.name_len, &e.name[0]); + e.name[e.name_len] = 0; + + if (cb(s, &e, cb_arg)) + break; + + off += ext2_to_cpu_16(e.rec_len); + } } static int ls_ext2 (void) { - return ext2fs_dir_iterate (fs, inode, DIRENT_FLAG_INCLUDE_EMPTY, - 0, ls_ext2_proc, NULL); + struct silo_ext2_state *s = sstate; + + iterate_dir(s, inode, ls_callback, 0); + + return 0; +} + +static int ino_size_ext2 (void) +{ + struct silo_ext2_state *s = sstate; + struct ext2_inode ei = { }; + + read_inode(s, inode, &ei); + + return ext2_to_cpu_32(ei.i_size); +} + +struct namei_cb_arg { + const char *name; + int len; + ino_t *ino; + int found; +}; + +static int lookup_cb(struct silo_ext2_state *s, struct ext2_dir_entry_2 *dirent, void *priv_data) +{ + struct namei_cb_arg *p = priv_data; + + if (p->len != dirent->name_len) + return 0; + if (strncmp(p->name, dirent->name, p->len)) + return 0; + p->found = 1; + *p->ino = ext2_to_cpu_32(dirent->inode); + return 1; } -static int ino_size_ext2 (void) { - struct ext2_inode ei; - int retval; +static int do_lookup(struct silo_ext2_state *s, __u32 dir_ino, const char *name, + int namelen, ino_t *ret_ino) +{ + struct namei_cb_arg arg; + + arg.name = name; + arg.len = namelen; + arg.ino = ret_ino; + arg.found = 0; + + iterate_dir(s, dir_ino, lookup_cb, &arg); - if ((retval = ext2fs_read_inode (fs, inode, &ei))) { - printf ("\n"); - ext2fs_error (retval); - printf ("\n"); + return arg.found ? 0 : -1; +} + +static int open_namei(struct silo_ext2_state *s, const char *name, + int namelen, ino_t root, ino_t base, ino_t *ret_ino); + +static int follow_link(struct silo_ext2_state *s, ino_t root, ino_t dir, + ino_t inode, ino_t *res_inode) +{ + struct ext2_inode ei = { }; + char symlink_buf[256]; + char *sym; + + read_inode(s, inode, &ei); + if (!is_symlink(ext2_to_cpu_16(ei.i_mode))) { + *res_inode = inode; + return 0; + } + sym = read_symlink(s, &ei, symlink_buf); + return open_namei(s, sym, ext2_to_cpu_32(ei.i_size), root, dir, res_inode); +} + +static int dir_namei(struct silo_ext2_state *s, ino_t root, ino_t dir, + const char *pathname, int pathlen, + const char **name, int *namelen, + ino_t *res_inode) +{ + const char *thisname; + int len, retval; + ino_t inode; + char c; + + if ((c = *pathname) == '/') { + dir = root; + pathname++; + pathlen--; + } + while (1) { + thisname = pathname; + for (len = 0; --pathlen >= 0; len++) { + c = *pathname++; + if (c == '/') + break; + } + if (pathlen < 0) + break; + retval = do_lookup(s, dir, thisname, len, &inode); + if (retval) + return retval; + retval = follow_link(s, root, dir, inode, &dir); + if (retval) + return retval; + } + *name = thisname; + *namelen = len; + *res_inode = dir; return 0; - } - return ei.i_size; } -static int namei_follow_ext2 (const char *filename) { - int ret = ext2fs_namei_follow (fs, root, root, filename, &inode); +static int open_namei(struct silo_ext2_state *s, const char *name, + int namelen, ino_t root, ino_t base, ino_t *ret_ino) +{ + const char *base_name; + ino_t dir_ino, inode; + int ret; + + ret = dir_namei(s, root, base, name, namelen, + &base_name, &namelen, &dir_ino); + if (ret) + return ret; + + if (!namelen) { + *ret_ino = dir_ino; + return 0; + } - ext2_fs_ops.have_inode = (inode) ? 1 : 0; + ret = do_lookup(s, dir_ino, base_name, namelen, &inode); + if (ret) + return ret; + + ret = follow_link(s, root, dir_ino, inode, &inode); + if (ret) + return ret; - return ret; + *ret_ino = inode; + return 0; } -static void print_error_ext2 (int error_val) { - ext2fs_error (error_val); +static int namei_follow_ext2 (const char *filename) +{ + int ret; + + ret = open_namei(sstate, filename, strlen(filename), + root, root, &inode); + + ext2_fs_ops.have_inode = inode ? 1 : 0; + + return ret; } -void close_ext2 (void) { - ext2fs_close(fs); +static void print_error_ext2 (int error_val) +{ + printf("error: %d", error_val); } struct fs_ops ext2_fs_ops = { @@ -152,14 +689,3 @@ .namei_follow = namei_follow_ext2, .have_inode = 0, }; - -/* These are silly stubs to satisfy libext2fs symbols */ -unsigned long time(void) -{ - return 0; -} - -void *realloc(void *p, int size) -{ - return NULL; -} diff -Naur silo-1.4.14.orig/second/ls.c silo-1.4.14/second/ls.c --- silo-1.4.14.orig/second/ls.c 2008-06-12 16:39:12.000000000 +0000 +++ silo-1.4.14/second/ls.c 2012-09-01 19:05:11.000000000 +0000 @@ -18,6 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include #include #include diff -Naur silo-1.4.14.orig/second/main.c silo-1.4.14/second/main.c --- silo-1.4.14.orig/second/main.c 2008-06-12 16:39:12.000000000 +0000 +++ silo-1.4.14/second/main.c 2012-09-01 19:05:11.000000000 +0000 @@ -25,8 +25,7 @@ /* TODO: This file is a good candidate for rewrite from scratch. */ #include -#include -#include +#include #include #ifndef NULL @@ -65,6 +64,7 @@ CMD_LS } load_cmd; enum arch architecture; +int sun4v_cpu; static int timer_status = 0; static char *initrd_start; static int initrd_size; diff -Naur silo-1.4.14.orig/second/misc.c silo-1.4.14/second/misc.c --- silo-1.4.14.orig/second/misc.c 2008-06-12 16:39:12.000000000 +0000 +++ silo-1.4.14/second/misc.c 2012-09-01 19:05:11.000000000 +0000 @@ -501,7 +501,7 @@ if ((i = prom_searchsiblings(i, "MicroSPARC-IIep")) != 0) { return sun4p; } - return sun4u; + buffer[4] = 'u'; } i = prom_getproperty (prom_root_node, "compatability", buffer, 8); @@ -517,8 +517,10 @@ return sun4d; case 'e': return sun4e; - case 'u': case 'v': + sun4v_cpu = 1; + /* FALLTHRU */ + case 'u': return sun4u; default: for(i = 0; i < NUM_SUN_MACHINES; i++) diff -Naur silo-1.4.14.orig/second/muldi3.S silo-1.4.14/second/muldi3.S --- silo-1.4.14.orig/second/muldi3.S 2008-06-12 16:39:12.000000000 +0000 +++ silo-1.4.14/second/muldi3.S 2012-09-01 19:11:45.000000000 +0000 @@ -20,6 +20,8 @@ .text .align 4 .globl __muldi3 + .register %g2,#scratch + .register %g3,#scratch __muldi3: save %sp, -104, %sp wr %g0, %i1, %y diff -Naur silo-1.4.14.orig/second/timer.c silo-1.4.14/second/timer.c --- silo-1.4.14.orig/second/timer.c 2008-06-12 16:39:12.000000000 +0000 +++ silo-1.4.14/second/timer.c 2012-09-01 19:05:11.000000000 +0000 @@ -156,7 +156,7 @@ } if (!foundcpu || !clock_frequency) clock_frequency = prom_getint(prom_root_node, "clock-frequency") / 100; - if (notimer) { + if (notimer && !sun4v_cpu) { sun4u_notimer = 1; __asm__ __volatile__ ("\t" "rd %%tick_cmpr, %%g1\n\t" diff -Naur silo-1.4.14.orig/silo/.gitignore silo-1.4.14/silo/.gitignore --- silo-1.4.14.orig/silo/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ silo-1.4.14/silo/.gitignore 2012-09-01 19:05:11.000000000 +0000 @@ -0,0 +1,6 @@ +# +# Generated files +# +floppy.h +silo +silocheck diff -Naur silo-1.4.14.orig/tilo/.gitignore silo-1.4.14/tilo/.gitignore --- silo-1.4.14.orig/tilo/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ silo-1.4.14/tilo/.gitignore 2012-09-01 19:05:11.000000000 +0000 @@ -0,0 +1,10 @@ +# +# Generated files +# +b.h +b.out +b2.h +b2.out +boot +boot2 +maketilo