diff options
Diffstat (limited to 'src/stream/fs')
-rw-r--r-- | src/stream/fs/Config.lb | 18 | ||||
-rw-r--r-- | src/stream/fs/blockdev.c | 411 | ||||
-rw-r--r-- | src/stream/fs/ext2fs.c | 793 | ||||
-rw-r--r-- | src/stream/fs/fat.c | 516 | ||||
-rw-r--r-- | src/stream/fs/iso9660.c | 338 | ||||
-rw-r--r-- | src/stream/fs/vfs.c | 176 |
6 files changed, 0 insertions, 2252 deletions
diff --git a/src/stream/fs/Config.lb b/src/stream/fs/Config.lb deleted file mode 100644 index 86d81f0dcc..0000000000 --- a/src/stream/fs/Config.lb +++ /dev/null @@ -1,18 +0,0 @@ -uses CONFIG_FS_EXT2 -uses CONFIG_FS_ISO9660 -uses CONFIG_FS_FAT - -object blockdev.o -object vfs.o - -if CONFIG_FS_EXT2 - object ext2fs.o -end - -if CONFIG_FS_ISO9660 - object iso9660.o -end - -if CONFIG_FS_FAT - object fat.o -end diff --git a/src/stream/fs/blockdev.c b/src/stream/fs/blockdev.c deleted file mode 100644 index aa818dd496..0000000000 --- a/src/stream/fs/blockdev.c +++ /dev/null @@ -1,411 +0,0 @@ -#include <console/console.h> -#include <fs/fs.h> -#include <arch/io.h> -#include <string.h> -#include <delay.h> -#include <pc80/ide.h> -#include <arch/byteorder.h> - -#define NUM_CACHE 64 -static unsigned char buf_cache[NUM_CACHE][512]; -static unsigned long cache_sect[NUM_CACHE]; - -static char dev_name[256]; - -int dev_type = -1; -int dev_drive = -1; -unsigned long part_start; -unsigned long part_length; -int using_devsize; - -unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base) -{ - unsigned long long result = 0,value; - - if (!base) { - base = 10; - if (*cp == '0') { - base = 8; - cp++; - if ((*cp == 'x') && isxdigit(cp[1])) { - cp++; - base = 16; - } - } - } - while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) - ? toupper(*cp) : *cp)-'A'+10) < base) { - result = result*base + value; - cp++; - } - if (endp) - *endp = (char *)cp; - return result; -} - -unsigned long long strtoull_with_suffix(const char *cp,char **endp,unsigned int base) -{ - unsigned long long result; - - if (!endp) { - return 0; - } - result = simple_strtoull(cp, endp, base); - switch (toupper(**endp)) { - case 'K': - result <<= 10; - ++*endp; - break; - case 'M': - result <<= 20; - ++*endp; - break; - case 'G': - result <<= 30; - ++*endp; - break; - } - return result; -} - -unsigned int get_le32(const unsigned char *p) -{ - return ((unsigned int) p[0] << 0) - | ((unsigned int) p[1] << 8) - | ((unsigned int) p[2] << 16) - | ((unsigned int) p[3] << 24); -} - -static inline int has_pc_part_magic(unsigned char *sect) -{ - return sect[510]==0x55 && sect[511]==0xAA; -} - -static inline int is_pc_extended_part(unsigned char type) -{ - return type==5 || type==0xf || type==0x85; -} - -/* IBM-PC/MS-DOS style partitioning scheme */ -static int open_pc_partition(int part, unsigned long *start_p, - unsigned long *length_p) -{ - /* Layout of PC partition table */ - struct pc_partition { - unsigned char boot; - unsigned char head; - unsigned char sector; - unsigned char cyl; - unsigned char type; - unsigned char e_head; - unsigned char e_sector; - unsigned char e_cyl; - unsigned char start_sect[4]; /* unaligned little endian */ - unsigned char nr_sects[4]; /* ditto */ - } *p; - unsigned char buf[512]; - - /* PC partition probe */ - if (!devread(0, 0, sizeof buf, buf)) { - printk_debug("device read failed\n"); - return 0; - } - if (!has_pc_part_magic(buf)) { - printk_debug("pc partition magic number not found\n"); - //printk_debug_hexdump(buf, 512); - return PARTITION_UNKNOWN; - } - p = (struct pc_partition *) (buf + 0x1be); - if (part < 4) { - /* Primary partition */ - p += part; - if (p->type==0 || is_pc_extended_part(p->type)) { - printk_info("Partition %d does not exist\n", part+1); - return 0; - } - *start_p = get_le32(p->start_sect); - *length_p = get_le32(p->nr_sects); - return 1; - } else { - /* Extended partition */ - int i; - int cur_part; - unsigned long ext_start, cur_table; - /* Search for the extended partition - * which contains logical partitions */ - for (i = 0; i < 4; i++) { - if (is_pc_extended_part(p[i].type)) - break; - } - if (i >= 4) { - printk_info("Extended partition not found\n"); - return 0; - } - printk_debug("Extended partition at %d\n", i+1); - /* Visit each logical partition labels */ - ext_start = get_le32(p[i].start_sect); - cur_table = ext_start; - cur_part = 4; - for (;;) { - printk_debug("cur_part=%d at %lu\n", cur_part, cur_table); - if (!devread(cur_table, 0, sizeof buf, buf)) - return 0; - if (!has_pc_part_magic(buf)) { - printk_debug("no magic\n"); - break; - } - - p = (struct pc_partition *) (buf + 0x1be); - /* First entry is the logical partition */ - if (cur_part == part) { - if (p->type==0) { - printk_info("Partition %d is empty\n", part+1); - return 0; - } - *start_p = cur_table + get_le32(p->start_sect); - *length_p = get_le32(p->nr_sects); - return 1; - } - /* Second entry is link to next partition */ - if (!is_pc_extended_part(p[1].type)) { - printk_debug("no link\n"); - break; - } - cur_table = ext_start + get_le32(p[1].start_sect); - - cur_part++; - } - printk_info("Logical partition %d not exist\n", part+1); - return 0; - } -} - -static void flush_cache(void) -{ - int i; - for (i = 0; i < NUM_CACHE; i++) - cache_sect[i] = (unsigned long) -1; -} - -static int parse_device_name(const char *name, int *type, int *drive, - int *part, uint64_t *offset, uint64_t *length) -{ - *offset = *length = 0; - - if (memcmp(name, "hd", 2) == 0) { - *type = DISK_IDE; - name += 2; - if (*name < 'a' || *name > 'z') { - printk_info("Invalid drive\n"); - return 0; - } - *drive = *name - 'a'; - name++; - } else if (memcmp(name, "mem", 3) == 0) { - *type = DISK_MEM; - name += 3; - *drive = 0; - } else { - printk_info("Unknown device type\n"); - return 0; - } - - *part = (int) simple_strtoull(name, (char **)&name, 0); - - if (*name == '@') { - name++; - *offset = strtoull_with_suffix(name, (char **)&name, 0); - if (*name == ',') - *length = strtoull_with_suffix(name+1, (char **)&name, 0); - printk_debug("offset=%#Lx length=%#Lx\n", *offset, *length); - } - - if (*name != '\0') { - printk_info("Can't parse device name\n"); - return 0; - } - - return 1; -} - -int devopen(const char *name, int *reopen) -{ - int type, drive, part, i; - uint64_t offset, length; - uint32_t disk_size = 0; - - /* Don't re-open the device that's already open */ - if (strcmp(name, dev_name) == 0) { - printk_debug("already open\n"); - *reopen = 1; - return 1; - } - *reopen = 0; - - if (!parse_device_name(name, &type, &drive, &part, &offset, &length)) { - printk_debug("failed to parse device name: %s\n", name); - return 0; - } - - /* Do simple sanity check first */ - if (offset & 0x1ff) { - printk_info("Device offset must be multiple of 512\n"); - return 0; - } - if (length & 0x1ff) { - printk_info("WARNING: length is rounded up to multiple of 512\n"); - length = (length + 0x1ff) & ~0x1ff; - } - - switch (type) { - case DISK_IDE: - printk_debug ("Trying polled ide\n"); - printk_debug ("Waiting for ide disks to spin up\n"); - printk_notice ("This is a hard coded delay and longer than necessary.\n"); - for (i = 0; i < 2; i++) { - printk_notice ("."); - delay(1); - } - printk_info ("\n"); - - if (ide_probe(drive) != 0) { - printk_debug("failed to open ide\n"); - return 0; - } - disk_size = (uint32_t) -1; /* FIXME */ - break; - case DISK_MEM: - disk_size = 1 << (32 - 9); /* 4GB/512-byte */ - break; - default: - printk_info("Unknown device type %d\n", type); - return 0; - } - - if (dev_type != type || dev_drive != drive) - flush_cache(); - - /* start with whole disk */ - dev_type = type; - dev_drive = drive; - part_start = 0; - part_length = disk_size; - using_devsize = 1; - - if (part != 0) { - /* partition is specified */ - int ret; - ret = open_pc_partition(part - 1, &part_start, &part_length); - if (ret == PARTITION_UNKNOWN) { - ret = open_eltorito_image(part - 1, &part_start, &part_length); - if (ret == PARTITION_UNKNOWN) { - printk_info("Unrecognized partitioning scheme\n"); - return 0; - } - } - if (ret == 0) { - printk_debug("can't open partition %d\n", part); - return 0; - } - - printk_debug("Partition %d start %lu length %lu\n", part, - part_start, part_length); - } - - if (offset) { - if (offset >= (uint64_t) part_length << 9) { - printk_info("Device offset is too high\n"); - return 0; - } - part_start += offset >> 9; - part_length -= offset >> 9; - printk_debug("after offset: start %lu, length %lu\n", part_start, part_length); - } - - if (length) { - if (length > (uint64_t) part_length << 9) { - printk_info("Specified length exceeds the size of device\n"); - return 0; - } - part_length = length >> 9; - printk_debug("after length: length %lu\n", part_length); - using_devsize = 0; - } - - strncpy(dev_name, name, sizeof dev_name-1); - - return 1; -} - -/* Read a sector from opened device with simple/stupid buffer cache */ -static void *read_sector(unsigned long sector) -{ - unsigned int hash; - void *buf; - - /* If reading memory, just return the memory as the buffer */ - if (dev_type == DISK_MEM) { - unsigned long phys = sector << 9; - //printk_debug("mem: %#lx\n", phys); - return (void *)phys; - } - - /* Search in the cache */ - hash = sector % NUM_CACHE; - buf = buf_cache[hash]; - if (cache_sect[hash] != sector) { - cache_sect[hash] = (unsigned long) -1; - switch (dev_type) { - case DISK_IDE: - if (ide_read(dev_drive, sector, buf) != 0) - goto readerr; - break; - default: - printk_info("read_sector: device not open\n"); - return 0; - } - cache_sect[hash] = sector; - } - return buf; - -readerr: - printk_info("Disk read error dev=%d drive=%d sector=%lu\n", - dev_type, dev_drive, sector); - dev_name[0] = '\0'; /* force re-open the device next time */ - return 0; -} - -int devread(unsigned long sector, unsigned long byte_offset, - unsigned long byte_len, void *buf) -{ - char *sector_buffer; - char *dest = buf; - unsigned long len; - - sector += byte_offset >> 9; - byte_offset &= 0x1ff; - - if (sector + ((byte_len + 0x1ff) >> 9) > part_length) { - printk_info("Attempt to read out of device/partition\n"); - printk_debug("sector=%lu part_length=%lu byte_len=%lu\n", - sector, part_length, byte_len); - return 0; - } - - while (byte_len > 0) { - sector_buffer = read_sector(part_start + sector); - if (!sector_buffer) { - printk_debug("read sector failed\n"); - return 0; - } - len = 512 - byte_offset; - if (len > byte_len) - len = byte_len; - memcpy(dest, sector_buffer + byte_offset, len); - sector++; - byte_offset = 0; - byte_len -= len; - dest += len; - } - return 1; -} diff --git a/src/stream/fs/ext2fs.c b/src/stream/fs/ext2fs.c deleted file mode 100644 index 9cf0bc6500..0000000000 --- a/src/stream/fs/ext2fs.c +++ /dev/null @@ -1,793 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999, 2001 Free Software Foundation, Inc. - * - * 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 <console/console.h> -#include <fs/fs.h> -#include <string.h> -#include <arch/byteorder.h> - -static int mapblock1, mapblock2; - -/* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */ -#define DEV_BSIZE 512 - -/* include/linux/fs.h */ -#define BLOCK_SIZE 1024 /* initial block size for superblock read */ -/* made up, defaults to 1 but can be passed via mount_opts */ -#define WHICH_SUPER 1 -/* kind of from fs/ext2/super.c */ -#define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE) /* = 2 */ - -/* include/asm-i386/types.h */ -typedef __signed__ char __s8; -typedef unsigned char __u8; -typedef __signed__ short __s16; -typedef unsigned short __u16; -typedef __signed__ int __s32; -typedef unsigned int __u32; - -/* - * Constants relative to the data blocks, from ext2_fs.h - */ -#define EXT2_NDIR_BLOCKS 12 -#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS -#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) -#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) -#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) - -/* include/linux/ext2_fs.h */ -struct ext2_super_block - { - __u32 s_inodes_count; /* Inodes count */ - __u32 s_blocks_count; /* Blocks count */ - __u32 s_r_blocks_count; /* Reserved blocks count */ - __u32 s_free_blocks_count; /* Free blocks count */ - __u32 s_free_inodes_count; /* Free inodes count */ - __u32 s_first_data_block; /* First Data Block */ - __u32 s_log_block_size; /* Block size */ - __s32 s_log_frag_size; /* Fragment size */ - __u32 s_blocks_per_group; /* # Blocks per group */ - __u32 s_frags_per_group; /* # Fragments per group */ - __u32 s_inodes_per_group; /* # Inodes per group */ - __u32 s_mtime; /* Mount time */ - __u32 s_wtime; /* Write time */ - __u16 s_mnt_count; /* Mount count */ - __s16 s_max_mnt_count; /* Maximal mount count */ - __u16 s_magic; /* Magic signature */ - __u16 s_state; /* File system state */ - __u16 s_errors; /* Behaviour when detecting errors */ - __u16 s_pad; - __u32 s_lastcheck; /* time of last check */ - __u32 s_checkinterval; /* max. time between checks */ - __u32 s_creator_os; /* OS */ - __u32 s_rev_level; /* Revision level */ - __u16 s_def_resuid; /* Default uid for reserved blocks */ - __u16 s_def_resgid; /* Default gid for reserved blocks */ - __u32 s_reserved[235]; /* Padding to the end of the block */ - }; - -struct ext2_group_desc - { - __u32 bg_block_bitmap; /* Blocks bitmap block */ - __u32 bg_inode_bitmap; /* Inodes bitmap block */ - __u32 bg_inode_table; /* Inodes table block */ - __u16 bg_free_blocks_count; /* Free blocks count */ - __u16 bg_free_inodes_count; /* Free inodes count */ - __u16 bg_used_dirs_count; /* Directories count */ - __u16 bg_pad; - __u32 bg_reserved[3]; - }; - -struct ext2_inode - { - __u16 i_mode; /* File mode */ - __u16 i_uid; /* Owner Uid */ - __u32 i_size; /* 4: Size in bytes */ - __u32 i_atime; /* Access time */ - __u32 i_ctime; /* 12: Creation time */ - __u32 i_mtime; /* Modification time */ - __u32 i_dtime; /* 20: Deletion Time */ - __u16 i_gid; /* Group Id */ - __u16 i_links_count; /* 24: Links count */ - __u32 i_blocks; /* Blocks count */ - __u32 i_flags; /* 32: File flags */ - union - { - struct - { - __u32 l_i_reserved1; - } - linux1; - struct - { - __u32 h_i_translator; - } - hurd1; - struct - { - __u32 m_i_reserved1; - } - masix1; - } - osd1; /* OS dependent 1 */ - __u32 i_block[EXT2_N_BLOCKS]; /* 40: Pointers to blocks */ - __u32 i_version; /* File version (for NFS) */ - __u32 i_file_acl; /* File ACL */ - __u32 i_dir_acl; /* Directory ACL */ - __u32 i_faddr; /* Fragment address */ - union - { - struct - { - __u8 l_i_frag; /* Fragment number */ - __u8 l_i_fsize; /* Fragment size */ - __u16 i_pad1; - __u32 l_i_reserved2[2]; - } - linux2; - struct - { - __u8 h_i_frag; /* Fragment number */ - __u8 h_i_fsize; /* Fragment size */ - __u16 h_i_mode_high; - __u16 h_i_uid_high; - __u16 h_i_gid_high; - __u32 h_i_author; - } - hurd2; - struct - { - __u8 m_i_frag; /* Fragment number */ - __u8 m_i_fsize; /* Fragment size */ - __u16 m_pad1; - __u32 m_i_reserved2[2]; - } - masix2; - } - osd2; /* OS dependent 2 */ - }; - -/* linux/limits.h */ -#define NAME_MAX 255 /* # chars in a file name */ - -/* linux/posix_type.h */ -typedef long linux_off_t; - -/* linux/ext2fs.h */ -#define EXT2_NAME_LEN 255 -struct ext2_dir_entry - { - __u32 inode; /* Inode number */ - __u16 rec_len; /* Directory entry length */ - __u8 name_len; /* Name length */ - __u8 file_type; - char name[EXT2_NAME_LEN]; /* File name */ - }; - -/* linux/ext2fs.h */ -/* - * EXT2_DIR_PAD defines the directory entries boundaries - * - * NOTE: It must be a multiple of 4 - */ -#define EXT2_DIR_PAD 4 -#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1) -#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \ - ~EXT2_DIR_ROUND) - - -/* ext2/super.c */ -#define log2(n) ffz(~(n)) - -#define EXT2_SUPER_MAGIC 0xEF53 /* include/linux/ext2_fs.h */ -#define EXT2_ROOT_INO 2 /* include/linux/ext2_fs.h */ -#define PATH_MAX 1024 /* include/linux/limits.h */ -#define MAX_LINK_COUNT 5 /* number of symbolic links to follow */ - -/* made up, these are pointers into FSYS_BUF */ -/* read once, always stays there: */ -#define SUPERBLOCK \ - ((struct ext2_super_block *)(FSYS_BUF)) -#define GROUP_DESC \ - ((struct ext2_group_desc *) \ - ((int)SUPERBLOCK + sizeof(struct ext2_super_block))) -#define INODE \ - ((struct ext2_inode *)((int)GROUP_DESC + EXT2_BLOCK_SIZE(SUPERBLOCK))) -#define DATABLOCK1 \ - ((int)((int)INODE + sizeof(struct ext2_inode))) -#define DATABLOCK2 \ - ((int)((int)DATABLOCK1 + EXT2_BLOCK_SIZE(SUPERBLOCK))) - -/* linux/ext2_fs.h */ -#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32)) -#define EXT2_ADDR_PER_BLOCK_BITS(s) (log2(EXT2_ADDR_PER_BLOCK(s))) - -/* linux/ext2_fs.h */ -#define EXT2_BLOCK_SIZE_BITS(s) (le32_to_cpu((s)->s_log_block_size) + 10) -/* kind of from ext2/super.c */ -#define EXT2_BLOCK_SIZE(s) (1 << EXT2_BLOCK_SIZE_BITS(s)) -/* linux/ext2fs.h */ -#define EXT2_DESC_PER_BLOCK(s) \ - (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc)) -/* linux/stat.h */ -#define S_IFMT 00170000 -#define S_IFLNK 0120000 -#define S_IFREG 0100000 -#define S_IFDIR 0040000 -#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) -#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) -#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) - -/* include/asm-i386/bitops.h */ -/* - * ffz = Find First Zero in word. Undefined if no zero exists, - * so code should check against ~0UL first.. - */ -#ifdef __i386 -static __inline__ unsigned long -ffz (unsigned long word) -{ - __asm__ ("bsfl %1,%0" -: "=r" (word) -: "r" (~word)); - return word; -} -#else /* !PPC */ -static __inline__ unsigned long - __ilog2(unsigned long x) -{ - unsigned long lz; - - asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x)); - return 31 - lz; -} -static __inline__ unsigned long -ffz(unsigned long x) -{ - if ((x = ~x) == 0) - return 32; - return __ilog2(x & -x); -} -#endif - -/* check filesystem types and read superblock into memory buffer */ -int -ext2fs_mount (void) -{ - int retval = 1; - - if ((((current_drive & 0x80) || (current_slice != 0)) - && (current_slice != PC_SLICE_TYPE_EXT2FS) - && (current_slice != PC_SLICE_TYPE_LINUX_RAID) - && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_EXT2FS)) - && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER))) - || part_length < (SBLOCK + (sizeof (struct ext2_super_block) / DEV_BSIZE)) - || !devread (SBLOCK, 0, sizeof (struct ext2_super_block), - (char *) SUPERBLOCK) - || le16_to_cpu(SUPERBLOCK->s_magic) != EXT2_SUPER_MAGIC) - retval = 0; - - return retval; -} - -/* Takes a file system block number and reads it into BUFFER. */ -static int -ext2_rdfsb (int fsblock, int buffer) -{ -#ifdef E2DEBUG - printk_debug ("fsblock %d buffer %d\n", fsblock, buffer); -#endif /* E2DEBUG */ - return devread (fsblock * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE), 0, - EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer); -} - -/* from - ext2/inode.c:ext2_bmap() -*/ -/* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into - a physical block (the location in the file system) via an inode. */ -static int -ext2fs_block_map (int logical_block) -{ - -#ifdef E2DEBUG - unsigned char *i; - for (i = (unsigned char *) INODE; - i < ((unsigned char *) INODE + sizeof (struct ext2_inode)); - i++) - { - printk_debug ("%c", "0123456789abcdef"[*i >> 4]); - printk_debug ("%c", "0123456789abcdef"[*i % 16]); - if (!((i + 1 - (unsigned char *) INODE) % 16)) - { - printk_debug ("\n"); - } - else - { - printk_debug (" "); - } - } - printk_debug ("logical block %d\n", logical_block); -#endif /* E2DEBUG */ - - /* if it is directly pointed to by the inode, return that physical addr */ - if (logical_block < EXT2_NDIR_BLOCKS) - { -#ifdef E2DEBUG - printk_debug ("returning %d\n", (unsigned char *) (le32_to_cpu(INODE->i_block[logical_block]))); - printk_debug ("returning %d\n", le32_to_cpu(INODE->i_block[logical_block])); -#endif /* E2DEBUG */ - return le32_to_cpu(INODE->i_block[logical_block]); - } - /* else */ - logical_block -= EXT2_NDIR_BLOCKS; - /* try the indirect block */ - if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK)) - { - if (mapblock1 != 1 - && !ext2_rdfsb (le32_to_cpu(INODE->i_block[EXT2_IND_BLOCK]), DATABLOCK1)) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - mapblock1 = 1; - return le32_to_cpu(((__u32 *) DATABLOCK1)[logical_block]); - } - /* else */ - logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK); - /* now try the double indirect block */ - if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2))) - { - int bnum; - if (mapblock1 != 2 - && !ext2_rdfsb (le32_to_cpu(INODE->i_block[EXT2_DIND_BLOCK]), DATABLOCK1)) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - mapblock1 = 2; - if ((bnum = le32_to_cpu(((__u32 *) DATABLOCK1) - [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)])) - != mapblock2 - && !ext2_rdfsb (bnum, DATABLOCK2)) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - mapblock2 = bnum; - return le32_to_cpu(((__u32 *) DATABLOCK2) - [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]); - } - /* else */ - mapblock2 = -1; - logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)); - if (mapblock1 != 3 - && !ext2_rdfsb (le32_to_cpu(INODE->i_block[EXT2_TIND_BLOCK]), DATABLOCK1)) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - mapblock1 = 3; - if (!ext2_rdfsb (le32_to_cpu(((__u32 *) DATABLOCK1) - [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) - * 2)]), - DATABLOCK2)) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - if (!ext2_rdfsb (le32_to_cpu(((__u32 *) DATABLOCK2) - [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)) - & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]), - DATABLOCK2)) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - return le32_to_cpu(((__u32 *) DATABLOCK2) - [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]); -} - -/* preconditions: all preconds of ext2fs_block_map */ -int -ext2fs_read (char *buf, int len) -{ - int logical_block; - int offset; - int map; - int ret = 0; - int size = 0; - -#ifdef E2DEBUG - static char hexdigit[] = "0123456789abcdef"; - unsigned char *i; - for (i = (unsigned char *) INODE; - i < ((unsigned char *) INODE + sizeof (struct ext2_inode)); - i++) - { - printk_debug ("%c", hexdigit[*i >> 4]); - printk_debug ("%c", hexdigit[*i % 16]); - if (!((i + 1 - (unsigned char *) INODE) % 16)) - { - printk_debug ("\n"); - } - else - { - printk_debug (" "); - } - } -#endif /* E2DEBUG */ - while (len > 0) - { - /* find the (logical) block component of our location */ - logical_block = filepos >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK); - offset = filepos & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1); - map = ext2fs_block_map (logical_block); -#ifdef E2DEBUG - printk_debug ("map=%d\n", map); -#endif /* E2DEBUG */ - if (map < 0) - break; - - size = EXT2_BLOCK_SIZE (SUPERBLOCK); - size -= offset; - if (size > len) - size = len; - - disk_read_func = disk_read_hook; - - devread (map * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE), - offset, size, buf); - - disk_read_func = 0; - - buf += size; - len -= size; - filepos += size; - ret += size; - } - - if (errnum) - ret = 0; - - return ret; -} - - -/* Based on: - def_blk_fops points to - blkdev_open, which calls (I think): - sys_open() - do_open() - open_namei() - dir_namei() which accesses current->fs->root - fs->root was set during original mount: - (something)... which calls (I think): - ext2_read_super() - iget() - __iget() - read_inode() - ext2_read_inode() - uses desc_per_block_bits, which is set in ext2_read_super() - also uses group descriptors loaded during ext2_read_super() - lookup() - ext2_lookup() - ext2_find_entry() - ext2_getblk() - -*/ - -/* preconditions: ext2fs_mount already executed, therefore supblk in buffer - * known as SUPERBLOCK - * returns: 0 if error, nonzero iff we were able to find the file successfully - * postconditions: on a nonzero return, buffer known as INODE contains the - * inode of the file we were trying to look up - * side effects: messes up GROUP_DESC buffer area - */ -int -ext2fs_dir (char *dirname) -{ - int current_ino = EXT2_ROOT_INO; /* start at the root */ - int updir_ino = current_ino; /* the parent of the current directory */ - int group_id; /* which group the inode is in */ - int group_desc; /* fs pointer to that group */ - int desc; /* index within that group */ - int ino_blk; /* fs pointer of the inode's information */ - int str_chk = 0; /* used to hold the results of a string compare */ - struct ext2_group_desc *gdp; - struct ext2_inode *raw_inode; /* inode info corresponding to current_ino */ - - char linkbuf[PATH_MAX]; /* buffer for following symbolic links */ - int link_count = 0; - - char *rest; - char ch; /* temp char holder */ - - int off; /* offset within block of directory entry (off mod blocksize) */ - int loc; /* location within a directory */ - int blk; /* which data blk within dir entry (off div blocksize) */ - long map; /* fs pointer of a particular block from dir entry */ - struct ext2_dir_entry *dp; /* pointer to directory entry */ -#ifdef E2DEBUG - unsigned char *i; -#endif /* E2DEBUG */ - - /* loop invariants: - current_ino = inode to lookup - dirname = pointer to filename component we are cur looking up within - the directory known pointed to by current_ino (if any) - */ - - while (1) - { -#ifdef E2DEBUG - printk_debug ("inode %d\n", current_ino); - printk_debug ("dirname=%s\n", dirname); -#endif /* E2DEBUG */ - - /* look up an inode */ - group_id = (current_ino - 1) / le32_to_cpu(SUPERBLOCK->s_inodes_per_group); - group_desc = group_id >> log2 (EXT2_DESC_PER_BLOCK (SUPERBLOCK)); - desc = group_id & (EXT2_DESC_PER_BLOCK (SUPERBLOCK) - 1); -#ifdef E2DEBUG - printk_debug ("ipg=%d, dpb=%d\n", le32_to_cpu(SUPERBLOCK->s_inodes_per_group), - EXT2_DESC_PER_BLOCK (SUPERBLOCK)); - printk_debug ("group_id=%d group_desc=%d desc=%d\n", group_id, group_desc, desc); -#endif /* E2DEBUG */ - if (!ext2_rdfsb ( - (WHICH_SUPER + group_desc + le32_to_cpu(SUPERBLOCK->s_first_data_block)), - (int) GROUP_DESC)) - { - return 0; - } - gdp = GROUP_DESC; - ino_blk = le32_to_cpu(gdp[desc].bg_inode_table) + - (((current_ino - 1) % le32_to_cpu(SUPERBLOCK->s_inodes_per_group)) - >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode))); -#ifdef E2DEBUG - printk_debug ("inode table fsblock=%d\n", ino_blk); -#endif /* E2DEBUG */ - if (!ext2_rdfsb (ino_blk, (int) INODE)) - { - return 0; - } - - /* reset indirect blocks! */ - mapblock2 = mapblock1 = -1; - - raw_inode = INODE + - ((current_ino - 1) - & (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode) - 1)); -#ifdef E2DEBUG - printk_debug ("ipb=%d, sizeof(inode)=%d\n", - (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)), - sizeof (struct ext2_inode)); - printk_debug ("inode=%x, raw_inode=%x\n", INODE, raw_inode); - printk_debug ("offset into inode table block=%d\n", (int) raw_inode - (int) INODE); - for (i = (unsigned char *) INODE; i <= (unsigned char *) raw_inode; - i++) - { - printk_debug ("%c", "0123456789abcdef"[*i >> 4]); - printk_debug ("%c", "0123456789abcdef"[*i % 16]); - if (!((i + 1 - (unsigned char *) INODE) % 16)) - { - printk_debug ("\n"); - } - else - { - printk_debug (" "); - } - } - printk_debug ("first word=%x\n", *((int *) raw_inode)); -#endif /* E2DEBUG */ - - /* copy inode to fixed location */ - memmove ((void *) INODE, (void *) raw_inode, sizeof (struct ext2_inode)); - -#ifdef E2DEBUG - printk_debug ("first word=%x\n", *((int *) INODE)); -#endif /* E2DEBUG */ - - /* If we've got a symbolic link, then chase it. */ - if (S_ISLNK (le16_to_cpu(INODE->i_mode))) - { - int len; - if (++link_count > MAX_LINK_COUNT) - { - errnum = ERR_SYMLINK_LOOP; - return 0; - } - - /* Find out how long our remaining name is. */ - len = 0; - while (dirname[len] && !isspace (dirname[len])) - len++; - - /* Get the symlink size. */ - filemax = le32_to_cpu(INODE->i_size); - if (filemax + len > sizeof (linkbuf) - 2) - { - errnum = ERR_FILELENGTH; - return 0; - } - - if (len) - { - /* Copy the remaining name to the end of the symlink data. - Note that DIRNAME and LINKBUF may overlap! */ - memmove (linkbuf + filemax, dirname, len); - } - linkbuf[filemax + len] = '\0'; - - /* Read the symlink data. */ - if (le32_to_cpu(INODE->i_blocks)) - { - /* Read the necessary blocks, and reset the file pointer. */ - len = file_read (linkbuf, filemax); - filepos = 0; - if (!len) - return 0; - } - else - { - /* Copy the data directly from the inode. */ - len = filemax; - memmove (linkbuf, (char *) INODE->i_block, len); - } - -#ifdef E2DEBUG - printk_debug ("symlink=%s\n", linkbuf); -#endif - - dirname = linkbuf; - if (*dirname == '/') - { - /* It's an absolute link, so look it up in root. */ - current_ino = EXT2_ROOT_INO; - updir_ino = current_ino; - } - else - { - /* Relative, so look it up in our parent directory. */ - current_ino = updir_ino; - } - - /* Try again using the new name. */ - continue; - } - - /* if end of filename, INODE points to the file's inode */ - if (!*dirname || isspace (*dirname)) - { - if (!S_ISREG (le16_to_cpu(INODE->i_mode))) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - filemax = le32_to_cpu(INODE->i_size); - return 1; - } - - /* else we have to traverse a directory */ - updir_ino = current_ino; - - /* skip over slashes */ - while (*dirname == '/') - dirname++; - - /* if this isn't a directory of sufficient size to hold our file, abort */ - if (!(le32_to_cpu(INODE->i_size)) || !S_ISDIR (le16_to_cpu(INODE->i_mode))) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - /* skip to next slash or end of filename (space) */ - for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; - rest++); - - /* look through this directory and find the next filename component */ - /* invariant: rest points to slash after the next filename component */ - *rest = 0; - loc = 0; - - do - { - -#ifdef E2DEBUG - printk_debug ("dirname=%s, rest=%s, loc=%d\n", dirname, rest, loc); -#endif /* E2DEBUG */ - - /* if our location/byte offset into the directory exceeds the size, - give up */ - if (loc >= le32_to_cpu(INODE->i_size)) - { - if (print_possibilities < 0) - { -# if 0 - putchar ('\n'); -# endif - } - else - { - errnum = ERR_FILE_NOT_FOUND; - *rest = ch; - } - return (print_possibilities < 0); - } - - /* else, find the (logical) block component of our location */ - blk = loc >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK); - - /* we know which logical block of the directory entry we are looking - for, now we have to translate that to the physical (fs) block on - the disk */ - map = ext2fs_block_map (blk); -#ifdef E2DEBUG - printk_debug ("fs block=%d\n", map); -#endif /* E2DEBUG */ - mapblock2 = -1; - if ((map < 0) || !ext2_rdfsb (map, DATABLOCK2)) - { - errnum = ERR_FSYS_CORRUPT; - *rest = ch; - return 0; - } - off = loc & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1); - dp = (struct ext2_dir_entry *) (DATABLOCK2 + off); - /* advance loc prematurely to next on-disk directory entry */ - loc += le16_to_cpu(dp->rec_len); - - /* NOTE: ext2fs filenames are NOT null-terminated */ - -#ifdef E2DEBUG - printk_debug ("directory entry ino=%d\n", le32_to_cpu(dp->inode)); - if (le32_to_cpu(dp->inode)) - printk_debug ("entry=%s\n", dp->name); -#endif /* E2DEBUG */ - - if (le32_to_cpu(dp->inode)) - { - int saved_c = dp->name[dp->name_len]; - - dp->name[dp->name_len] = 0; - str_chk = substring (dirname, dp->name); - -# ifndef STAGE1_5 - if (print_possibilities && ch != '/' - && (!*dirname || str_chk <= 0)) - { - if (print_possibilities > 0) - print_possibilities = -print_possibilities; - print_a_completion (dp->name); - } -# endif - - dp->name[dp->name_len] = saved_c; - } - - } - while (!le32_to_cpu(dp->inode) || (str_chk || (print_possibilities && ch != '/'))); - - current_ino = le32_to_cpu(dp->inode); - *(dirname = rest) = ch; - } - /* never get here */ -} diff --git a/src/stream/fs/fat.c b/src/stream/fs/fat.c deleted file mode 100644 index 01e4e03cc2..0000000000 --- a/src/stream/fs/fat.c +++ /dev/null @@ -1,516 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2000, 2001 Free Software Foundation, Inc. - * - * 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 <console/console.h> -#include <string.h> -#include <fs/fs.h> -#include <fs/fat.h> -#include <arch/byteorder.h> - -struct fat_superblock -{ - int fat_offset; - int fat_length; - int fat_size; - int root_offset; - int root_max; - int data_offset; - - int num_sectors; - int num_clust; - int clust_eof_marker; - int sects_per_clust; - int sectsize_bits; - int clustsize_bits; - int root_cluster; - - int cached_fat; - int file_cluster; - int current_cluster_num; - int current_cluster; -}; - -/* pointer(s) into filesystem info buffer for DOS stuff */ -#define FAT_SUPER ( (struct fat_superblock *) \ - ( FSYS_BUF + 32256) )/* 512 bytes long */ -#define FAT_BUF ( FSYS_BUF + 30208 ) /* 4 sector FAT buffer */ -#define NAME_BUF ( FSYS_BUF + 29184 ) /* Filename buffer (833 bytes) */ - -#define FAT_CACHE_SIZE 2048 - -#ifdef __i386 -static __inline__ unsigned long -log2 (unsigned long word) -{ - __asm__ ("bsfl %1,%0" - : "=r" (word) - : "r" (word)); - return word; -} -#else /* !PPC */ -static __inline__ unsigned long -__ilog2(unsigned long x) -{ - unsigned long lz; - - asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x)); - return 31 - lz; -} -static __inline__ unsigned long -log2(unsigned long x) -{ - return __ilog2(x & -x); -} -#endif - -int -fat_mount (void) -{ - struct fat_bpb bpb; - __u32 magic, first_fat; - - /* Check partition type for harddisk */ - if (((current_drive & 0x80) || (current_slice != 0)) - && ! IS_PC_SLICE_TYPE_FAT (current_slice) - && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_MSDOS))) - return 0; - - /* Read bpb */ - if (! devread (0, 0, sizeof (bpb), (char *) &bpb)) - return 0; - - /* Check if the number of sectors per cluster is zero here, to avoid - zero division. */ - if (bpb.sects_per_clust == 0) - return 0; - - FAT_SUPER->sectsize_bits = log2(FAT_CVT_U16(bpb.bytes_per_sect)); - FAT_SUPER->clustsize_bits - = FAT_SUPER->sectsize_bits + log2(bpb.sects_per_clust); - -printk_debug("BytsPerSec = %d\n", FAT_CVT_U16(bpb.bytes_per_sect)); -printk_debug("SecPerClus = %d\n", bpb.sects_per_clust); - - /* Fill in info about super block */ - FAT_SUPER->num_sectors = FAT_CVT_U16(bpb.short_sectors) - ? FAT_CVT_U16(bpb.short_sectors) : FAT_CVT_U32(bpb.long_sectors); - -printk_debug("TotSec16 = %d\n", FAT_CVT_U16(bpb.short_sectors)); -printk_debug("TotSec32 = %d\n", FAT_CVT_U32(bpb.long_sectors)); - - /* FAT offset and length */ - FAT_SUPER->fat_offset = FAT_CVT_U16(bpb.reserved_sects); - FAT_SUPER->fat_length = FAT_CVT_U16(bpb.fat_length) - ? FAT_CVT_U16(bpb.fat_length) : FAT_CVT_U32(bpb.fat32_length); - -printk_debug("RsvdSecCnt = %d\n", FAT_CVT_U16(bpb.reserved_sects)); -printk_debug("FATSx16 = %d\n", FAT_CVT_U16(bpb.fat_length)); -printk_debug("FATSx32 = %d\n", FAT_CVT_U32(bpb.fat32_length)); - - /* Rootdir offset and length for FAT12/16 */ - FAT_SUPER->root_offset = - FAT_SUPER->fat_offset + bpb.num_fats * FAT_SUPER->fat_length; - FAT_SUPER->root_max = FAT_DIRENTRY_LENGTH * FAT_CVT_U16(bpb.dir_entries); - -printk_debug("RootEntCnt = %d\n", FAT_CVT_U16(bpb.dir_entries)); - - /* Data offset and number of clusters */ - FAT_SUPER->data_offset = - FAT_SUPER->root_offset - + ((FAT_SUPER->root_max - 1) >> FAT_SUPER->sectsize_bits) + 1; - FAT_SUPER->num_clust = - 2 + ((FAT_SUPER->num_sectors - FAT_SUPER->data_offset) - / bpb.sects_per_clust); - FAT_SUPER->sects_per_clust = bpb.sects_per_clust; - - if (!bpb.fat_length) - { - /* This is a FAT32 */ - if (FAT_CVT_U16(bpb.dir_entries)) - return 0; - -printk_debug("We seem to be FAT32\n"); -printk_debug("ExtFlags = 0x%x\n", FAT_CVT_U16(bpb.flags)); -printk_debug("RootClus = %d\n", FAT_CVT_U32(bpb.root_cluster)); - if (FAT_CVT_U16(bpb.flags) & 0x0080) - { - /* FAT mirroring is disabled, get active FAT */ - int active_fat = FAT_CVT_U16(bpb.flags) & 0x000f; - if (active_fat >= bpb.num_fats) - return 0; - FAT_SUPER->fat_offset += active_fat * FAT_SUPER->fat_length; - } - - FAT_SUPER->fat_size = 8; - FAT_SUPER->root_cluster = FAT_CVT_U32(bpb.root_cluster); - - /* Yes the following is correct. FAT32 should be called FAT28 :) */ - FAT_SUPER->clust_eof_marker = 0xffffff8; - } - else - { - if (!FAT_SUPER->root_max) - return 0; - -printk_debug("We seem to be FAT12/16\n"); - FAT_SUPER->root_cluster = -1; - if (FAT_SUPER->num_clust > FAT_MAX_12BIT_CLUST) - { - FAT_SUPER->fat_size = 4; - FAT_SUPER->clust_eof_marker = 0xfff8; - } - else - { - FAT_SUPER->fat_size = 3; - FAT_SUPER->clust_eof_marker = 0xff8; - } - } - - /* Now do some sanity checks */ - - if (FAT_CVT_U16(bpb.bytes_per_sect) != (1 << FAT_SUPER->sectsize_bits) - || FAT_CVT_U16(bpb.bytes_per_sect) != SECTOR_SIZE - || bpb.sects_per_clust != (1 << (FAT_SUPER->clustsize_bits - - FAT_SUPER->sectsize_bits)) - || FAT_SUPER->num_clust <= 2 - || (FAT_SUPER->fat_size * FAT_SUPER->num_clust / (2 * SECTOR_SIZE) - > FAT_SUPER->fat_length)) - return 0; - - /* kbs: Media check on first FAT entry [ported from PUPA] */ - - if (!devread(FAT_SUPER->fat_offset, 0, - sizeof(first_fat), (char *)&first_fat)) - return 0; - -printk_debug("Media = 0x%x\n", bpb.media); - - if (FAT_SUPER->fat_size == 8) - { - first_fat = le32_to_cpu(first_fat) & 0x0fffffff; - magic = 0x0fffff00; - } - else if (FAT_SUPER->fat_size == 4) - { - first_fat = le32_to_cpu(first_fat) & 0x0000ffff; - magic = 0xff00; - } - else - { - first_fat = le32_to_cpu(first_fat) & 0x00000fff; - magic = 0x0f00; - } - - if (first_fat != (magic | bpb.media)) - return 0; - - FAT_SUPER->cached_fat = - 2 * FAT_CACHE_SIZE; - return 1; -} - -int -fat_read (char *buf, int len) -{ - int logical_clust; - int offset; - int ret = 0; - int size; - - if (FAT_SUPER->file_cluster < 0) - { - /* root directory for fat16 */ - size = FAT_SUPER->root_max - filepos; - if (size > len) - size = len; - if (!devread(FAT_SUPER->root_offset, filepos, size, buf)) - return 0; - filepos += size; - return size; - } - - logical_clust = filepos >> FAT_SUPER->clustsize_bits; - offset = (filepos & ((1 << FAT_SUPER->clustsize_bits) - 1)); - if (logical_clust < FAT_SUPER->current_cluster_num) - { - FAT_SUPER->current_cluster_num = 0; - FAT_SUPER->current_cluster = FAT_SUPER->file_cluster; - } - - while (len > 0) - { - int sector; - while (logical_clust > FAT_SUPER->current_cluster_num) - { - /* calculate next cluster */ - int fat_entry = - FAT_SUPER->current_cluster * FAT_SUPER->fat_size; - int next_cluster; - int cached_pos = (fat_entry - FAT_SUPER->cached_fat); - - if (cached_pos < 0 || - (cached_pos + FAT_SUPER->fat_size) > 2*FAT_CACHE_SIZE) - { - FAT_SUPER->cached_fat = (fat_entry & ~(2*SECTOR_SIZE - 1)); - cached_pos = (fat_entry - FAT_SUPER->cached_fat); - sector = FAT_SUPER->fat_offset - + FAT_SUPER->cached_fat / (2*SECTOR_SIZE); - if (!devread (sector, 0, FAT_CACHE_SIZE, (char*) FAT_BUF)) - return 0; - } - next_cluster = FAT_CVT_U32(FAT_BUF + (cached_pos >> 1)); - if (FAT_SUPER->fat_size == 3) - { - if (cached_pos & 1) - next_cluster >>= 4; - next_cluster &= 0xFFF; - } - else if (FAT_SUPER->fat_size == 4) - next_cluster &= 0xFFFF; - - if (next_cluster >= FAT_SUPER->clust_eof_marker) - return ret; - if (next_cluster < 2 || next_cluster >= FAT_SUPER->num_clust) - { - errnum = ERR_FSYS_CORRUPT; - return 0; - } - - FAT_SUPER->current_cluster = next_cluster; - FAT_SUPER->current_cluster_num++; - } - - sector = FAT_SUPER->data_offset + - ((FAT_SUPER->current_cluster - 2) << (FAT_SUPER->clustsize_bits - - FAT_SUPER->sectsize_bits)); - size = (1 << FAT_SUPER->clustsize_bits) - offset; - if (size > len) - size = len; - - disk_read_func = disk_read_hook; - - devread(sector, offset, size, buf); - - disk_read_func = 0; - - len -= size; - buf += size; - ret += size; - filepos += size; - logical_clust++; - offset = 0; - } - return errnum ? 0 : ret; -} - -int -fat_dir (char *dirname) -{ - char *rest, ch, dir_buf[FAT_DIRENTRY_LENGTH]; - char *filename = (char *) NAME_BUF; - int attrib = FAT_ATTRIB_DIR; -#ifndef STAGE1_5 - int do_possibilities = 0; -#endif - - /* XXX I18N: - * the positions 2,4,6 etc are high bytes of a 16 bit unicode char - */ - static unsigned char longdir_pos[] = - { 1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30 }; - int slot = -2; - int alias_checksum = -1; - - FAT_SUPER->file_cluster = FAT_SUPER->root_cluster; - filepos = 0; - FAT_SUPER->current_cluster_num = MAXINT; - - /* main loop to find desired directory entry */ - loop: - - /* 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 (attrib & FAT_ATTRIB_DIR) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - return 1; - } - - /* continue with the file/directory name interpretation */ - - while (*dirname == '/') - dirname++; - - if (!(attrib & FAT_ATTRIB_DIR)) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - /* Directories don't have a file size */ - filemax = MAXINT; - - for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++); - - *rest = 0; - -# ifndef STAGE1_5 - if (print_possibilities && ch != '/') - do_possibilities = 1; -# endif - - while (1) - { - if (fat_read (dir_buf, FAT_DIRENTRY_LENGTH) != FAT_DIRENTRY_LENGTH - || dir_buf[0] == 0) - { - if (!errnum) - { -# ifndef STAGE1_5 - if (print_possibilities < 0) - { -#if 0 - putchar ('\n'); -#endif - return 1; - } -# endif /* STAGE1_5 */ - - errnum = ERR_FILE_NOT_FOUND; - *rest = ch; - } - - return 0; - } - - if (FAT_DIRENTRY_ATTRIB (dir_buf) == FAT_ATTRIB_LONGNAME) - { - /* This is a long filename. The filename is build from back - * to front and may span multiple entries. To bind these - * entries together they all contain the same checksum over - * the short alias. - * - * The id field tells if this is the first entry (the last - * part) of the long filename, and also at which offset this - * belongs. - * - * We just write the part of the long filename this entry - * describes and continue with the next dir entry. - */ - int i, offset; - unsigned char id = FAT_LONGDIR_ID(dir_buf); - - if ((id & 0x40)) - { - id &= 0x3f; - slot = id; - filename[slot * 13] = 0; - alias_checksum = FAT_LONGDIR_ALIASCHECKSUM(dir_buf); - } - - if (id != slot || slot == 0 - || alias_checksum != FAT_LONGDIR_ALIASCHECKSUM(dir_buf)) - { - alias_checksum = -1; - continue; - } - - slot--; - offset = slot * 13; - - for (i=0; i < 13; i++) - filename[offset+i] = dir_buf[longdir_pos[i]]; - continue; - } - - if (!FAT_DIRENTRY_VALID (dir_buf)) - continue; - - if (alias_checksum != -1 && slot == 0) - { - int i; - unsigned char sum; - - slot = -2; - for (sum = 0, i = 0; i< 11; i++) - sum = ((sum >> 1) | (sum << 7)) + dir_buf[i]; - - if (sum == alias_checksum) - { -# ifndef STAGE1_5 - if (do_possibilities) - goto print_filename; -# endif /* STAGE1_5 */ - - if (substring (dirname, filename) == 0) - break; - } - } - - /* XXX convert to 8.3 filename format here */ - { - int i, j, c; - - for (i = 0; i < 8 && (c = filename[i] = tolower (dir_buf[i])) - && !isspace (c); i++); - - filename[i++] = '.'; - - for (j = 0; j < 3 && (c = filename[i + j] = tolower (dir_buf[8 + j])) - && !isspace (c); j++); - - if (j == 0) - i--; - - filename[i + j] = 0; - } - -# ifndef STAGE1_5 - if (do_possibilities) - { - print_filename: - if (substring (dirname, filename) <= 0) - { - if (print_possibilities > 0) - print_possibilities = -print_possibilities; - print_a_completion (filename); - } - continue; - } -# endif /* STAGE1_5 */ - - if (substring (dirname, filename) == 0) - break; - } - - *(dirname = rest) = ch; - - attrib = FAT_DIRENTRY_ATTRIB (dir_buf); - filemax = FAT_DIRENTRY_FILELENGTH (dir_buf); - filepos = 0; - FAT_SUPER->file_cluster = FAT_DIRENTRY_FIRST_CLUSTER (dir_buf); - FAT_SUPER->current_cluster_num = MAXINT; - - /* go back to main loop at top of function */ - goto loop; -} diff --git a/src/stream/fs/iso9660.c b/src/stream/fs/iso9660.c deleted file mode 100644 index 9d36a5cf54..0000000000 --- a/src/stream/fs/iso9660.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * ISO 9660 filesystem backend for GRUB (GRand Unified Bootloader) - * including Rock Ridge Extensions support - * - * Copyright (C) 1998, 1999 Kousuke Takai <tak@kmc.kyoto-u.ac.jp> - * - * 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. - */ -/* - * References: - * linux/fs/isofs/rock.[ch] - * mkisofs-1.11.1/diag/isoinfo.c - * mkisofs-1.11.1/iso9660.h - * (all are written by Eric Youngdale) - * - * Modifications by: - * Leonid Lisovskiy <lly@pisem.net> 2003 - */ - -/* - * Modified to make it work with FILO - * 2003-10 by SONE Takeshi - */ - -#include <console/console.h> -#include <fs/fs.h> -#include <fs/iso9660.h> -#include <string.h> - -struct iso_superblock { - unsigned long vol_sector; - - unsigned long file_start; -}; - -#define ISO_SUPER ((struct iso_superblock *)(FSYS_BUF)) -#define PRIMDESC ((struct iso_primary_descriptor *)(FSYS_BUF + 2048)) -#define DIRREC ((struct iso_directory_record *)(FSYS_BUF + 4096)) -#define RRCONT_BUF ((unsigned char *)(FSYS_BUF + 6144)) -#define NAME_BUF ((unsigned char *)(FSYS_BUF + 8192)) - -static int -iso9660_devread (int sector, int byte_offset, int byte_len, char *buf) -{ - /* FILO uses 512-byte "soft" sector, and ISO-9660 uses 2048-byte - * CD-ROM sector */ - return devread(sector<<2, byte_offset, byte_len, buf); -} - -int -iso9660_mount (void) -{ - unsigned int sector; - - /* - * Because there is no defined slice type ID for ISO-9660 filesystem, - * this test will pass only either (1) if entire disk is used, or - * (2) if current partition is BSD style sub-partition whose ID is - * ISO-9660. - */ - /*if ((current_partition != 0xFFFFFF) - && !IS_PC_SLICE_TYPE_BSD_WITH_FS(current_slice, FS_ISO9660)) - return 0;*/ - - /* - * Currently, only FIRST session of MultiSession disks are supported !!! - */ - for (sector = 16 ; sector < 32 ; sector++) - { - if (!iso9660_devread(sector, 0, sizeof(*PRIMDESC), (char *)PRIMDESC)) - break; - /* check ISO_VD_PRIMARY and ISO_STANDARD_ID */ - if (isonum_711(PRIMDESC->type) == ISO_VD_PRIMARY && - !__builtin_memcmp(PRIMDESC->id, "CD001", 5)) - { - ISO_SUPER->vol_sector = sector; - ISO_SUPER->file_start = 0; - fsmax = isonum_733(PRIMDESC->volume_space_size); - return 1; - } - } - - return 0; -} - -int -iso9660_dir (char *dirname) -{ - struct iso_directory_record *idr; - RR_ptr_t rr_ptr; - struct rock_ridge *ce_ptr; - unsigned int pathlen; - int size; - unsigned int extent; - unsigned int rr_len; - unsigned char file_type; - unsigned char rr_flag; - - idr = (struct iso_directory_record *)&PRIMDESC->root_directory_record; - ISO_SUPER->file_start = 0; - - do - { - while (*dirname == '/') /* skip leading slashes */ - dirname++; - /* pathlen = strcspn(dirname, "/\n\t "); */ - for (pathlen = 0 ; - dirname[pathlen] - && !isspace(dirname[pathlen]) && dirname[pathlen] != '/' ; - pathlen++) - ; - - size = isonum_733(idr->size); - extent = isonum_733(idr->extent); - - while (size > 0) - { - if (!iso9660_devread(extent, 0, ISO_SECTOR_SIZE, (char *)DIRREC)) - { - errnum = ERR_FSYS_CORRUPT; - return 0; - } - extent++; - - idr = (struct iso_directory_record *)DIRREC; - for (; isonum_711(idr->length) > 0; - idr = (struct iso_directory_record *)((char *)idr + isonum_711(idr->length)) ) - { - const char *name = idr->name; - unsigned int name_len = isonum_711(idr->name_len); - - file_type = (isonum_711(idr->flags) & 2) ? ISO_DIRECTORY : ISO_REGULAR; - if (name_len == 1) - { - if ((name[0] == 0) || /* self */ - (name[0] == 1)) /* parent */ - continue; - } - if (name_len > 2 && - name[name_len - 2] == ';' && - name[name_len - 1] == '1') - { - name_len -= 2; /* truncate trailing file version */ - if (name_len > 1 && name[name_len - 1] == '.') - name_len--; /* truncate trailing dot */ - } - - /* - * Parse Rock-Ridge extension - */ - rr_len = (isonum_711(idr->length) - isonum_711(idr->name_len) - - sizeof(struct iso_directory_record) - + sizeof(idr->name)); - rr_ptr.ptr = ((unsigned char *)idr + isonum_711(idr->name_len) - + sizeof(struct iso_directory_record) - - sizeof(idr->name)); - if (rr_ptr.i & 1) - rr_ptr.i++, rr_len--; - ce_ptr = 0; - rr_flag = RR_FLAG_NM | RR_FLAG_PX; - - while (rr_len >= 4) - { - if (rr_ptr.rr->version != 1) - { -#ifndef STAGE1_5 - if (debug) - printk_debug( - "Non-supported version (%d) RockRidge chunk " - "`%c%c'\n", rr_ptr.rr->version, - rr_ptr.rr->signature[0], - rr_ptr.rr->signature[1]); -#endif - break; - } - else if (rr_ptr.rr->signature[0] == 'R' - && rr_ptr.rr->signature[1] == 'R' - && rr_ptr.rr->len >= 5) - rr_flag &= isonum_711(rr_ptr.rr->u.RR.flags); - else if (rr_ptr.rr->signature[0] == 'N' - && rr_ptr.rr->signature[1] == 'M') - { - name = rr_ptr.rr->u.NM.name; - name_len = rr_ptr.rr->len - 5; - rr_flag &= ~RR_FLAG_NM; - } - else if (rr_ptr.rr->signature[0] == 'P' - && rr_ptr.rr->signature[1] == 'X' - && rr_ptr.rr->len >= 36) - { - unsigned int mode = isonum_733(rr_ptr.rr->u.PX.mode); - file_type = ((mode & POSIX_S_IFMT) - == POSIX_S_IFREG - ? ISO_REGULAR - : ((mode & POSIX_S_IFMT) - == POSIX_S_IFDIR - ? ISO_DIRECTORY : ISO_OTHER)); - rr_flag &= ~RR_FLAG_PX; - } - else if (rr_ptr.rr->signature[0] == 'C' - && rr_ptr.rr->signature[1] == 'E' - && rr_ptr.rr->len >= 28) - ce_ptr = rr_ptr.rr; - if (!rr_flag) - /* - * There is no more extension we expects... - */ - break; - rr_len -= rr_ptr.rr->len; - rr_ptr.ptr += rr_ptr.rr->len; - if (rr_len < 4 && ce_ptr != 0) - { - /* preserve name before loading new extent. */ - if( RRCONT_BUF <= (unsigned char *)name - && (unsigned char *)name < RRCONT_BUF + ISO_SECTOR_SIZE ) - { - memcpy(NAME_BUF, name, name_len); - name = NAME_BUF; - } - rr_ptr.ptr = RRCONT_BUF + isonum_733(ce_ptr->u.CE.offset); - rr_len = isonum_733(ce_ptr->u.CE.size); - if (!iso9660_devread(isonum_733(ce_ptr->u.CE.extent), 0, ISO_SECTOR_SIZE, RRCONT_BUF)) - { - errnum = 0; /* this is not fatal. */ - break; - } - ce_ptr = 0; - } - } /* rr_len >= 4 */ - - filemax = MAXINT; - if (name_len >= pathlen - && !__builtin_memcmp(name, dirname, pathlen)) - { - if (dirname[pathlen] == '/' || !print_possibilities) - { - /* - * DIRNAME is directory component of pathname, - * or we are to open a file. - */ - if (pathlen == name_len) - { - if (dirname[pathlen] == '/') - { - if (file_type != ISO_DIRECTORY) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - goto next_dir_level; - } - if (file_type != ISO_REGULAR) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - ISO_SUPER->file_start = isonum_733(idr->extent); - filepos = 0; - filemax = isonum_733(idr->size); - return 1; - } - } - else /* Completion */ - { -#ifndef STAGE1_5 - if (print_possibilities > 0) - print_possibilities = -print_possibilities; - memcpy(NAME_BUF, name, name_len); - NAME_BUF[name_len] = '\0'; - print_a_completion (NAME_BUF); -#endif - } - } - } /* for */ - - size -= ISO_SECTOR_SIZE; - } /* size>0 */ - - if (dirname[pathlen] == '/' || print_possibilities >= 0) - { - errnum = ERR_FILE_NOT_FOUND; - return 0; - } - -next_dir_level: - dirname += pathlen; - - } while (*dirname == '/'); - - return 1; -} - -int -iso9660_read (char *buf, int len) -{ - int sector, blkoffset, size, ret; - - if (ISO_SUPER->file_start == 0) - return 0; - - ret = 0; - blkoffset = filepos & (ISO_SECTOR_SIZE - 1); - sector = filepos >> ISO_SECTOR_BITS; - while (len > 0) - { - size = ISO_SECTOR_SIZE - blkoffset; - if (size > len) - size = len; - - disk_read_func = disk_read_hook; - - if (!iso9660_devread(ISO_SUPER->file_start + sector, blkoffset, size, buf)) - return 0; - - disk_read_func = 0; - - len -= size; - buf += size; - ret += size; - filepos += size; - sector++; - blkoffset = 0; - } - - return ret; -} diff --git a/src/stream/fs/vfs.c b/src/stream/fs/vfs.c deleted file mode 100644 index 4a298cef2a..0000000000 --- a/src/stream/fs/vfs.c +++ /dev/null @@ -1,176 +0,0 @@ -/* Interface between GRUB's fs drivers and application code */ - -#include <console/console.h> -#include <fs/fs.h> -#include <string.h> -#include <stdlib.h> - -int filepos; -int filemax; -fs_error_t errnum; -void (*disk_read_hook) (int, int, int); -void (*disk_read_func) (int, int, int); -char FSYS_BUF[FSYS_BUFLEN]; -int fsmax; - -struct fsys_entry { - char *name; - int (*mount_func) (void); - int (*read_func) (char *buf, int len); - int (*dir_func) (char *dirname); - void (*close_func) (void); - int (*embed_func) (int *start_sector, int needed_sectors); -}; - -struct fsys_entry fsys_table[] = { -# if CONFIG_FS_FAT == 1 - {"fat", fat_mount, fat_read, fat_dir, 0, 0}, -# endif -# if CONFIG_FS_EXT2 == 1 - {"ext2fs", ext2fs_mount, ext2fs_read, ext2fs_dir, 0, 0}, -# endif -# if CONFIG_FS_ISO9660 == 1 - {"iso9660", iso9660_mount, iso9660_read, iso9660_dir, 0, 0}, -# endif -}; - -/* NULLFS is used to read images from raw device */ -static int nullfs_dir(char *name) -{ - uint64_t dev_size; - - if (name) { - printk_debug("can't have a named file\n"); - return 0; - } - - dev_size = (uint64_t) part_length << 9; - /* GRUB code doesn't like 2GB or bigger files */ - if (dev_size > 0x7fffffff) - dev_size = 0x7fffffff; - filemax = dev_size; - return 1; -} - -static int nullfs_read(char *buf, int len) -{ - if (devread(filepos>>9, filepos&0x1ff, len, buf)) { - filepos += len; - return len; - } else - return 0; -} - -static struct fsys_entry nullfs = - {"nullfs", 0, nullfs_read, nullfs_dir, 0, 0}; - -static struct fsys_entry *fsys; - -int mount_fs(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(fsys_table); i++) { - if (fsys_table[i].mount_func()) { - fsys = &fsys_table[i]; - printk_info("Mounted %s\n", fsys->name); - return 1; - } - } - fsys = 0; - printk_info("Unknown filesystem type\n"); - return 0; -} - -int file_open(const char *filename) -{ - char *dev = 0; - const char *path; - int len; - int retval = 0; - int reopen; - - path = strchr(filename, ':'); - if (path) { - len = path - filename; - path++; - dev = malloc(len + 1); - memcpy(dev, filename, len); - dev[len] = '\0'; - } else { - /* No colon is given. Is this device or filename? */ - if (filename[0] == '/') { - /* Anything starts with '/' must be a filename */ - dev = 0; - path = filename; - } else { - dev = strdup(filename); - path = 0; - } - } - - if (dev && dev[0]) { - if (!devopen(dev, &reopen)) { - fsys = 0; - goto out; - } - if (!reopen) - fsys = 0; - } - - if (path) { - if (!fsys || fsys==&nullfs) { - if (!mount_fs()) - goto out; - } - using_devsize = 0; - if (!path[0]) { - printk_info("No filename is given\n"); - goto out; - } - } else - fsys = &nullfs; - - filepos = 0; - errnum = 0; - if (!fsys->dir_func((char *) path)) { - printk_info("File not found\n"); - goto out; - } - retval = 1; -out: - if (dev) - free(dev); - return retval; -} - -int file_read(void *buf, unsigned long len) -{ - if (filepos < 0 || filepos > filemax) - filepos = filemax; - if (len < 0 || len > filemax-filepos) - len = filemax - filepos; - errnum = 0; - return fsys->read_func(buf, len); -} - -int file_seek(unsigned long offset) -{ - filepos = offset; - return filepos; -} - -unsigned long file_pos(void) -{ - return filepos; -} - -unsigned long file_size(void) -{ - return filemax; -} - -void file_close(void) -{ -} - |