diff options
35 files changed, 729 insertions, 589 deletions
@@ -102,7 +102,8 @@ endif .PHONY: $(filter-out $(private-targets), $(MAKECMDGOALS)) $(filter-out $(private-targets), $(MAKECMDGOALS)): $(MAKE) -C $(OBJDIR) -f $(CURDIR)/Makefile SRC="$(topdir)" \ - OBJ=$(OBJDIR) objdir=$(OBJDIR) $(MAKECMDGOALS) + OBJ=$(OBJDIR) objdir=$(OBJDIR) EFI_BUILD=$(EFI_BUILD) \ + $(MAKECMDGOALS) unittest: printf "Executing unit tests\n" @@ -111,7 +112,7 @@ unittest: regression: $(MAKE) -C tests SRC="$(topdir)/tests" OBJ="$(topdir)/tests" \ - objdir=$(OBJDIR) \ + objdir=$(OBJDIR) EFI_BUILD=$(EFI_BUILD) \ -f $(topdir)/tests/Makefile all test: unittest regression @@ -284,17 +285,17 @@ subdirs: $(BSUBDIRS) $(ISUBDIRS) $(sort $(ISUBDIRS) $(BSUBDIRS)): @mkdir -p $@ - $(MAKE) -C $@ SRC="$(SRC)/$@" OBJ="$(OBJ)/$@" \ + $(MAKE) -C $@ SRC="$(SRC)/$@" OBJ="$(OBJ)/$@" EFI_BUILD=$(EFI_BUILD) \ -f $(SRC)/$@/Makefile $(MAKECMDGOALS) $(ITARGET): @mkdir -p $@ - $(MAKE) -C $@ SRC="$(SRC)/$@" OBJ="$(OBJ)/$@" \ + $(MAKE) -C $@ SRC="$(SRC)/$@" OBJ="$(OBJ)/$@" EFI_BUILD=$(EFI_BUILD) \ -f $(SRC)/$@/Makefile $(MAKECMDGOALS) $(BINFILES): @mkdir -p $@ - $(MAKE) -C $@ SRC="$(SRC)/$@" OBJ="$(OBJ)/$@" \ + $(MAKE) -C $@ SRC="$(SRC)/$@" OBJ="$(OBJ)/$@" EFI_BUILD=$(EFI_BUILD) \ -f $(SRC)/$@/Makefile $(MAKECMDGOALS) # @@ -309,7 +310,7 @@ gpxe: core installer: installer-local set -e; for i in $(ISUBDIRS); \ do $(MAKE) -C $$i SRC="$(SRC)/$$i" OBJ="$(OBJ)/$$i" \ - -f $(SRC)/$$i/Makefile all; done + EFI_BUILD=$(EFI_BUILD) -f $(SRC)/$$i/Makefile all; done installer-local: $(ITARGET) $(BINFILES) @@ -317,7 +318,7 @@ installer-local: $(ITARGET) $(BINFILES) strip: strip-local set -e; for i in $(ISUBDIRS); \ do $(MAKE) -C $$i SRC="$(SRC)/$$i" OBJ="$(OBJ)/$$i" \ - -f $(SRC)/$$i/Makefile strip; done + EFI_BUILD=$(EFI_BUILD) -f $(SRC)/$$i/Makefile strip; done -ls -l $(BOBJECTS) $(IOBJECTS) strip-local: @@ -355,7 +356,7 @@ install: set -e ; for i in $(INSTALLSUBDIRS) ; \ do $(MAKE) -C $$i SRC="$(SRC)/$$i" OBJ="$(OBJ)/$$i" \ BITS="$(BITS)" AUXDIR="$(AUXDIR)/efi$(BITS)" \ - -f $(SRC)/$$i/Makefile $@; done + EFI_BUILD=$(EFI_BUILD) -f $(SRC)/$$i/Makefile $@; done -install -m 644 $(INSTALLABLE_MODULES) $(INSTALLROOT)$(AUXDIR)/efi$(BITS) install -m 644 com32/elflink/ldlinux/$(LDLINUX) $(INSTALLROOT)$(AUXDIR)/efi$(BITS) endif diff --git a/com32/Makefile b/com32/Makefile index 5efda1ce..3e7a7700 100644 --- a/com32/Makefile +++ b/com32/Makefile @@ -6,7 +6,7 @@ subdirs: $(SUBDIRS) $(SUBDIRS): @mkdir -p $(OBJ)/$@ $(MAKE) -C $(OBJ)/$@ SRC="$(SRC)"/$@ OBJ="$(OBJ)"/$@/ \ - -f $(SRC)/$@/Makefile $(MAKECMDGOALS) + EFI_BUILD=$(EFI_BUILD) -f $(SRC)/$@/Makefile $(MAKECMDGOALS) all tidy dist clean spotless install: subdirs diff --git a/com32/chain/options.c b/com32/chain/options.c index 2b519394..e9c4a627 100644 --- a/com32/chain/options.c +++ b/com32/chain/options.c @@ -138,6 +138,7 @@ static void usage(void) " - strict w/o any value is the same as strict=2", " relax The same as strict=0", " prefmbr On hybrid MBR/GPT disks, prefer legacy layout", +" exit Don't read anything after this keyword", "", " file=<file> Load and execute <file>", " seg=<s[:o[:i]]> Load file at <s:o>, jump to <s:i>", @@ -194,6 +195,8 @@ int opt_parse_args(int argc, char *argv[]) for (i = 1; i < argc; i++) { if (!strncmp(argv[i], "file=", 5)) { opt.file = argv[i] + 5; + } else if (!strncmp(argv[i], "exit", 4)) { + break; } else if (!strcmp(argv[i], "nofile")) { opt.file = NULL; } else if (!strncmp(argv[i], "seg=", 4)) { diff --git a/com32/elflink/ldlinux/cli.c b/com32/elflink/ldlinux/cli.c index 6ff30c64..3119b11f 100644 --- a/com32/elflink/ldlinux/cli.c +++ b/com32/elflink/ldlinux/cli.c @@ -125,7 +125,7 @@ const char *edit_cmdline(const char *input, int top /*, int width */ , int (*pDraw_Menu) (int, int, int), void (*show_fkey) (int), bool *timedout) { - char cmdline[MAX_CMDLINE_LEN] = { }; + static char cmdline[MAX_CMDLINE_LEN] = { }; int key, len, prev_len, cursor; int redraw = 0; int x, y; diff --git a/com32/lib/pci/scan.c b/com32/lib/pci/scan.c index fe00fc25..20a3e2a6 100644 --- a/com32/lib/pci/scan.c +++ b/com32/lib/pci/scan.c @@ -603,6 +603,7 @@ int get_module_name_from_alias(struct pci_domain *domain, char *modules_alias_pa char sub_product_id[16]; FILE *f; struct pci_device *dev=NULL; + int valid_lines=0; /* Intializing the linux_kernel_module for each pci device to "unknown" */ /* adding a dev_info member if needed */ @@ -630,6 +631,7 @@ int get_module_name_from_alias(struct pci_domain *domain, char *modules_alias_pa if ((line[0] == '#') || (strstr(line,"alias pci:v")==NULL)) continue; + valid_lines++; /* Resetting temp buffer*/ memset(module_name,0,sizeof(module_name)); memset(vendor_id,0,sizeof(vendor_id)); @@ -725,5 +727,11 @@ int get_module_name_from_alias(struct pci_domain *domain, char *modules_alias_pa } } fclose(f); + /* If no valid line was found in the module.alias, + * we shall report it as broken/empty/non-existing */ + if (valid_lines == 0) { + return -ENOMODULESALIAS; + } + return 0; } diff --git a/core/fs/btrfs/btrfs.c b/core/fs/btrfs/btrfs.c index 53e11050..58e1fe68 100644 --- a/core/fs/btrfs/btrfs.c +++ b/core/fs/btrfs/btrfs.c @@ -81,7 +81,8 @@ static int btrfs_comp_chunk_map(struct btrfs_chunk_map_item *m1, } /* insert a new chunk mapping item */ -static void insert_map(struct fs_info *fs, struct btrfs_chunk_map_item *item) +static void insert_chunk_item(struct fs_info *fs, + struct btrfs_chunk_map_item *item) { struct btrfs_info * const bfs = fs->fs_info; struct btrfs_chunk_map *chunk_map = &bfs->chunk_map; @@ -113,6 +114,22 @@ static void insert_map(struct fs_info *fs, struct btrfs_chunk_map_item *item) chunk_map->cur_length++; } +static inline void insert_map(struct fs_info *fs, struct btrfs_disk_key *key, + struct btrfs_chunk *chunk) +{ + struct btrfs_stripe *stripe = &chunk->stripe; + struct btrfs_stripe *stripe_end = stripe + chunk->num_stripes; + struct btrfs_chunk_map_item item; + + item.logical = key->offset; + item.length = chunk->length; + for ( ; stripe < stripe_end; stripe++) { + item.devid = stripe->devid; + item.physical = stripe->offset; + insert_chunk_item(fs, &item); + } +} + /* * from sys_chunk_array or chunk_tree, we can convert a logical address to * a physical address we can not support multi device case yet @@ -330,7 +347,6 @@ static int next_slot(struct fs_info *fs, struct btrfs_disk_key *key, static void btrfs_read_sys_chunk_array(struct fs_info *fs) { struct btrfs_info * const bfs = fs->fs_info; - struct btrfs_chunk_map_item item; struct btrfs_disk_key *key; struct btrfs_chunk *chunk; int cur; @@ -342,12 +358,7 @@ static void btrfs_read_sys_chunk_array(struct fs_info *fs) cur += sizeof(*key); chunk = (struct btrfs_chunk *)(bfs->sb.sys_chunk_array + cur); cur += btrfs_chunk_item_size(chunk->num_stripes); - /* insert to mapping table, ignore multi stripes */ - item.logical = key->offset; - item.length = chunk->length; - item.devid = chunk->stripe.devid; - item.physical = chunk->stripe.offset;/*ignore other stripes */ - insert_map(fs, &item); + insert_map(fs, key, chunk); } } @@ -355,14 +366,18 @@ static void btrfs_read_sys_chunk_array(struct fs_info *fs) static void btrfs_read_chunk_tree(struct fs_info *fs) { struct btrfs_info * const bfs = fs->fs_info; + struct btrfs_disk_key ignore_key; struct btrfs_disk_key search_key; struct btrfs_chunk *chunk; - struct btrfs_chunk_map_item item; struct btrfs_path path; if (!(bfs->sb.flags & BTRFS_SUPER_FLAG_METADUMP)) { if (bfs->sb.num_devices > 1) printf("warning: only support single device btrfs\n"); + + ignore_key.objectid = BTRFS_DEV_ITEMS_OBJECTID; + ignore_key.type = BTRFS_DEV_ITEM_KEY; + /* read chunk from chunk_tree */ search_key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID; search_key.type = BTRFS_CHUNK_ITEM_KEY; @@ -371,16 +386,18 @@ static void btrfs_read_chunk_tree(struct fs_info *fs) search_tree(fs, bfs->sb.chunk_root, &search_key, &path); do { do { + /* skip information about underlying block + * devices. + */ + if (!btrfs_comp_keys_type(&ignore_key, + &path.item.key)) + continue; if (btrfs_comp_keys_type(&search_key, - &path.item.key)) + &path.item.key)) break; + chunk = (struct btrfs_chunk *)(path.data); - /* insert to mapping table, ignore stripes */ - item.logical = path.item.key.offset; - item.length = chunk->length; - item.devid = chunk->stripe.devid; - item.physical = chunk->stripe.offset; - insert_map(fs, &item); + insert_map(fs, &path.item.key, chunk); } while (!next_slot(fs, &search_key, &path)); if (btrfs_comp_keys_type(&search_key, &path.item.key)) break; diff --git a/core/fs/btrfs/btrfs.h b/core/fs/btrfs/btrfs.h index 8f519a9c..32e7c703 100644 --- a/core/fs/btrfs/btrfs.h +++ b/core/fs/btrfs/btrfs.h @@ -56,6 +56,8 @@ typedef u64 __le64; #define BTRFS_MAX_LEVEL 8 #define BTRFS_MAX_CHUNK_ENTRIES 256 +#define BTRFS_DEV_ITEMS_OBJECTID 1ULL + #define BTRFS_FT_REG_FILE 1 #define BTRFS_FT_DIR 2 #define BTRFS_FT_SYMLINK 7 diff --git a/core/fs/xfs/xfs.c b/core/fs/xfs/xfs.c index e42e9526..6f459737 100644 --- a/core/fs/xfs/xfs.c +++ b/core/fs/xfs/xfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 Paulo Alcantara <pcacjr@zytor.com> + * Copyright (c) 2012-2015 Paulo Alcantara <pcacjr@zytor.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -74,10 +74,13 @@ static int xfs_readdir(struct file *file, struct dirent *dirent) return -1; } - if (core->di_format == XFS_DINODE_FMT_LOCAL) + switch (core->di_format) { + case XFS_DINODE_FMT_LOCAL: return xfs_fmt_local_readdir(file, dirent, core); - else if (core->di_format == XFS_DINODE_FMT_EXTENTS) + case XFS_DINODE_FMT_EXTENTS: + case XFS_DINODE_FMT_BTREE: return xfs_fmt_extents_readdir(file, dirent, core); + } return -1; } @@ -117,8 +120,10 @@ static int xfs_next_extent(struct inode *inode, uint32_t lstart) goto out; if (core->di_format == XFS_DINODE_FMT_EXTENTS) { - bmbt_irec_get(&rec, (xfs_bmbt_rec_t *)&core->di_literal_area[0] + - XFS_PVT(inode)->i_cur_extent++); + bmbt_irec_get(&rec, (xfs_bmbt_rec_t *)XFS_DFORK_PTR(core, + XFS_DATA_FORK) + + XFS_PVT(inode)->i_cur_extent); + XFS_PVT(inode)->i_cur_extent++; bno = fsblock_to_bytes(fs, rec.br_startblock) >> BLOCK_SHIFT(fs); @@ -130,7 +135,7 @@ static int xfs_next_extent(struct inode *inode, uint32_t lstart) } else if (core->di_format == XFS_DINODE_FMT_BTREE) { xfs_debug("XFS_DINODE_FMT_BTREE"); index = XFS_PVT(inode)->i_cur_extent++; - rblock = (xfs_bmdr_block_t *)&core->di_literal_area[0]; + rblock = XFS_DFORK_PTR(core, XFS_DATA_FORK); fsize = XFS_DFORK_SIZE(core, fs, XFS_DATA_FORK); pp = XFS_BMDR_PTR_ADDR(rblock, 1, xfs_bmdr_maxrecs(fsize, 0)); bno = fsblock_to_bytes(fs, be64_to_cpu(pp[0])) >> BLOCK_SHIFT(fs); @@ -278,9 +283,9 @@ static int xfs_readlink(struct inode *inode, char *buf) } if (core->di_format == XFS_DINODE_FMT_LOCAL) { - memcpy(buf, (char *)&core->di_literal_area[0], pathlen); + memcpy(buf, XFS_DFORK_PTR(core, XFS_DATA_FORK), pathlen); } else if (core->di_format == XFS_DINODE_FMT_EXTENTS) { - bmbt_irec_get(&rec, (xfs_bmbt_rec_t *)&core->di_literal_area[0]); + bmbt_irec_get(&rec, XFS_DFORK_PTR(core, XFS_DATA_FORK)); db = fsblock_to_bytes(fs, rec.br_startblock) >> BLOCK_SHIFT(fs); dir_buf = xfs_dir2_dirblks_get_cached(fs, db, rec.br_blockcount); @@ -331,7 +336,7 @@ out: return NULL; } -static inline int xfs_read_superblock(struct fs_info *fs, xfs_sb_t *sb) +static inline int xfs_read_sb(struct fs_info *fs, xfs_sb_t *sb) { struct disk *disk = fs->fs_dev->disk; @@ -376,24 +381,21 @@ static int xfs_fs_init(struct fs_info *fs) SECTOR_SHIFT(fs) = disk->sector_shift; SECTOR_SIZE(fs) = 1 << SECTOR_SHIFT(fs); - if (xfs_read_superblock(fs, &sb)) { + if (xfs_read_sb(fs, &sb)) { xfs_error("Superblock read failed"); goto out; } - - if (!xfs_is_valid_magicnum(&sb)) { + if (!xfs_is_valid_sb(&sb)) { xfs_error("Invalid superblock"); goto out; } - - xfs_debug("magicnum 0x%lX", be32_to_cpu(sb.sb_magicnum)); + xfs_debug("sb magic: 0x%lX", be32_to_cpu(sb.sb_magicnum)); info = xfs_new_sb_info(&sb); if (!info) { xfs_error("Failed to fill in filesystem-specific info structure"); goto out; } - fs->fs_info = info; xfs_debug("block_shift %u blocksize 0x%lX (%lu)", info->block_shift, diff --git a/core/fs/xfs/xfs.h b/core/fs/xfs/xfs.h index 0d953d89..65acd17f 100644 --- a/core/fs/xfs/xfs.h +++ b/core/fs/xfs/xfs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 Paulo Alcantara <pcacjr@zytor.com> + * Copyright (c) 2012-2015 Paulo Alcantara <pcacjr@zytor.com> * * Some parts borrowed from Linux kernel tree (linux/fs/xfs): * @@ -30,15 +30,16 @@ #include "xfs_types.h" #include "xfs_ag.h" -#define xfs_error(fmt, args...) \ - ({ \ - printf("%s:%u: xfs - [ERROR] " fmt "\n", __func__, __LINE__, ## args); \ +#define xfs_error(fmt, args...) \ + ({ \ + dprintf("%s:%u: xfs - [error] " fmt "\n", __func__, __LINE__, \ + ## args); \ }) -#define xfs_debug(fmt, args...) \ - ({ \ - dprintf("%s:%u: xfs - [DEBUG] " fmt "\n", __func__, __LINE__, \ - ## args); \ +#define xfs_debug(fmt, args...) \ + ({ \ + dprintf("%s:%u: xfs - [debug] " fmt "\n", __func__, __LINE__, \ + ## args); \ }) struct xfs_fs_info; @@ -115,6 +116,9 @@ struct xfs_fs_info; #define XFS_DIR2_NULL_DATAPTR ((uint32_t)0) +#define XFS_DIR3_BLOCK_MAGIC 0x58444233 /* XDB3: single block dirs */ +#define XFS_DIR3_DATA_MAGIC 0x58444433 /* XDD3: multiblock dirs */ + /* File types and modes */ #define S_IFMT 00170000 #define S_IFSOCK 0140000 @@ -345,8 +349,19 @@ typedef struct xfs_dinode { /* di_next_unlinked is the only non-core field in the old dinode */ uint32_t di_next_unlinked;/* agi unlinked list ptr */ - uint8_t di_literal_area[1]; -} __attribute__((packed)) xfs_dinode_t; + + /* start of the extended dinode, writable fields */ + uint32_t di_crc; /* CRC of the inode */ + uint64_t di_changecount; /* number of attribute changes */ + uint64_t di_lsn; /* flush sequence */ + uint64_t di_flags2; /* more random flags */ + uint8_t di_pad2[16]; + + /* fields only written to during inode creation */ + xfs_timestamp_t di_crtime; /* time created */ + uint64_t di_ino; /* inode number */ + uuid_t di_uuid; /* UUID of the filesystem */ +} __attribute__((__packed__)) xfs_dinode_t; /* * Inode size for given fs. @@ -358,23 +373,41 @@ typedef struct xfs_dinode { (XFS_BTREE_LBLOCK_LEN - sizeof(xfs_bmdr_block_t)) /* + * Size of the core inode on disk. Version 1 and 2 inodes have + * the same size, but version 3 has grown a few additional fields. + */ +static inline unsigned int xfs_dinode_size(int version) +{ + if (version == 3) + return sizeof(struct xfs_dinode); + return offsetof(struct xfs_dinode, di_crc); +} + +/* * Inode data & attribute fork sizes, per inode. */ #define XFS_DFORK_Q(dip) ((dip)->di_forkoff != 0) #define XFS_DFORK_BOFF(dip) ((int)((dip)->di_forkoff << 3)) -#define XFS_DFORK_DSIZE(dip, fs) \ - (XFS_DFORK_Q(dip) ? \ - XFS_DFORK_BOFF(dip) : \ - XFS_LITINO(fs)) -#define XFS_DFORK_ASIZE(dip, fs) \ - (XFS_DFORK_Q(dip) ? \ - XFS_LITINO(fs) - XFS_DFORK_BOFF(dip) : \ - 0) -#define XFS_DFORK_SIZE(dip, fs, w) \ - ((w) == XFS_DATA_FORK ? \ - XFS_DFORK_DSIZE(dip, fs) : \ - XFS_DFORK_ASIZE(dip, fs)) +#define XFS_DFORK_DSIZE(dip, fs) \ + (XFS_DFORK_Q(dip) ? \ + XFS_DFORK_BOFF(dip) : \ + XFS_LITINO(fs)) +#define XFS_DFORK_ASIZE(dip, fs) \ + (XFS_DFORK_Q(dip) ? \ + XFS_LITINO(fs) - XFS_DFORK_BOFF(dip) : \ + 0) +#define XFS_DFORK_SIZE(dip, fs, w) \ + ((w) == XFS_DATA_FORK ? \ + XFS_DFORK_DSIZE(dip, fs) : \ + XFS_DFORK_ASIZE(dip, fs)) + +#define XFS_DFORK_DPTR(dip) \ + ((void *)((uint8_t *)dip + xfs_dinode_size(dip->di_version))) +#define XFS_DFORK_APTR(dip) \ + ((void *)((uint8_t *)XFS_DFORK_DPTR(dip) + XFS_DFORK_BOFF(dip))) +#define XFS_DFORK_PTR(dip,w) \ + ((w) == XFS_DATA_FORK ? XFS_DFORK_DPTR(dip) : XFS_DFORK_APTR(dip)) struct xfs_inode { xfs_agblock_t i_agblock; @@ -405,13 +438,12 @@ typedef struct xfs_dir2_sf_hdr { 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 */ + uint8_t name[]; /* name, variable size */ } __attribute__((__packed__)) 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_hdr_t hdr; /* shortform header */ + xfs_dir2_sf_entry_t list[]; /* shortform entries */ } __attribute__((__packed__)) xfs_dir2_sf_t; typedef xfs_ino_t xfs_intino_t; @@ -482,6 +514,21 @@ typedef struct xfs_dir2_data_unused { /* uint16_t tag; */ /* starting offset of us */ } __attribute__((__packed__)) xfs_dir2_data_unused_t; +struct xfs_dir3_blk_hdr { + uint32_t magic; /* magic number */ + uint32_t crc; /* CRC of block */ + uint64_t blkno; /* first block of the buffer */ + uint64_t lsn; /* sequence number of last write */ + uuid_t uuid; /* filesystem we belong to */ + uint64_t owner; /* inode that owns the block */ +} __attribute__((__packed__)); + +struct xfs_dir3_data_hdr { + struct xfs_dir3_blk_hdr hdr; + xfs_dir2_data_free_t best_free[XFS_DIR2_DATA_FD_COUNT]; + uint32_t pad; /* 64 bit alignment */ +} __attribute__((__packed__)); + /** * rol32 - rotate a 32-bit value left * @word: value to rotate @@ -501,10 +548,17 @@ static inline uint32_t rol32(uint32_t word, signed int shift) static inline int xfs_dir2_data_entsize(int n) { - return (int)roundup(offsetof(struct xfs_dir2_data_entry, name[0]) + n + + return (int)roundup(offsetof(struct xfs_dir2_data_entry, name[0]) + n + (unsigned int)sizeof(uint16_t), XFS_DIR2_DATA_ALIGN); } +static inline int xfs_dir3_data_entsize(int n) +{ + return (int)roundup(offsetof(struct xfs_dir2_data_entry, name[0]) + n + + (unsigned int)sizeof(uint16_t) + sizeof(uint8_t), + XFS_DIR2_DATA_ALIGN); +} + static inline uint16_t * xfs_dir2_data_entry_tag_p(struct xfs_dir2_data_entry *dep) { @@ -597,27 +651,69 @@ typedef struct xfs_dir2_leaf { xfs_dir2_leaf_entry_t ents[]; /* entries */ } __attribute__((__packed__)) xfs_dir2_leaf_t; +typedef struct xfs_da3_blkinfo { + /* + * the node link manipulation code relies on the fact that the first + * element of this structure is the struct xfs_da_blkinfo so it can + * ignore the differences in the rest of the structures. + */ + xfs_da_blkinfo_t hdr; + uint32_t crc; /* CRC of block */ + uint64_t blkno; /* first block of the buffer */ + uint64_t lsn; /* sequence number of last write */ + uuid_t uuid; /* filesystem we belong to */ + uint64_t owner; /* inode that owns the block */ +} __attribute__((__packed__)) xfs_da3_blkinfo_t; + +typedef struct xfs_dir3_leaf_hdr { + xfs_da3_blkinfo_t info; /* header for da routines */ + uint16_t count; /* count of entries */ + uint16_t stale; /* count of stale entries */ + uint32_t pad; /* 64 bit alignment */ +} __attribute__((__packed__)) xfs_dir3_leaf_hdr_t; + +typedef struct xfs_dir3_leaf { + xfs_dir3_leaf_hdr_t hdr; /* leaf header */ + xfs_dir2_leaf_entry_t ents[]; /* entries */ +} __attribute__((__packed__)) xfs_dir3_leaf_t; + #define XFS_DA_NODE_MAGIC 0xfebeU /* magic number: non-leaf blocks */ #define XFS_ATTR_LEAF_MAGIC 0xfbeeU /* magic number: attribute leaf blks */ #define XFS_DIR2_LEAF1_MAGIC 0xd2f1U /* magic number: v2 dirlf single blks */ #define XFS_DIR2_LEAFN_MAGIC 0xd2ffU /* magic number: V2 dirlf multi blks */ +#define XFS_DA3_NODE_MAGIC 0x3ebe /* magic number: non-leaf blocks */ +#define XFS_ATTR3_LEAF_MAGIC 0x3bee /* magic number: attribute leaf blks */ +#define XFS_DIR3_LEAF1_MAGIC 0x3df1 /* magic number: v2 dirlf single blks */ +#define XFS_DIR3_LEAFN_MAGIC 0x3dff /* magic number: v2 dirlf multi blks */ + +#define XFS_DIR3_LEAF1_MAGIC 0x3df1 /* magic number: v2 dirlf single blks */ +#define XFS_DIR3_LEAFN_MAGIC 0x3dff /* magic number: v2 dirlf multi blks */ + +typedef struct xfs_da_node_hdr { + xfs_da_blkinfo_t info; /* block type, links, etc. */ + uint16_t count; /* count of active entries */ + uint16_t level; /* level above leaves (leaf == 0) */ +} __attribute__((__packed__)) xfs_da_node_hdr_t; + +typedef struct xfs_da_node_entry { + uint32_t hashval; /* hash value for this descendant */ + uint32_t before; /* Btree block before this key */ +} __attribute__((__packed__)) xfs_da_node_entry_t; + 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 { - uint32_t hashval; /* hash value for this descendant */ - uint32_t before; /* Btree block before this key */ - } btree[1]; + xfs_da_node_hdr_t hdr; + xfs_da_node_entry_t btree[]; } __attribute__((__packed__)) xfs_da_intnode_t; -typedef struct xfs_da_node_hdr xfs_da_node_hdr_t; -typedef struct xfs_da_node_entry xfs_da_node_entry_t; +typedef struct xfs_da3_node_hdr { + xfs_da3_blkinfo_t info; /* block type, links, etc. */ + uint16_t count; /* count of active entries */ + uint16_t level; /* level above leaves (leaf == 0) */ + uint32_t pad32; +} __attribute__((__packed__)) xfs_da3_node_hdr_t; -static inline bool xfs_is_valid_magicnum(const xfs_sb_t *sb) +static inline bool xfs_is_valid_sb(const xfs_sb_t *sb) { return sb->sb_magicnum == *(uint32_t *)XFS_SB_MAGIC; } diff --git a/core/fs/xfs/xfs_dinode.c b/core/fs/xfs/xfs_dinode.c index 55be6e2d..dff73826 100644 --- a/core/fs/xfs/xfs_dinode.c +++ b/core/fs/xfs/xfs_dinode.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 Paulo Alcantara <pcacjr@zytor.com> + * Copyright (c) 2012-2015 Paulo Alcantara <pcacjr@zytor.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as diff --git a/core/fs/xfs/xfs_dir2.c b/core/fs/xfs/xfs_dir2.c index de37ef7c..2f5928a5 100644 --- a/core/fs/xfs/xfs_dir2.c +++ b/core/fs/xfs/xfs_dir2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 Paulo Alcantara <pcacjr@zytor.com> + * Copyright (c) 2012-2015 Paulo Alcantara <pcacjr@zytor.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -67,30 +67,29 @@ uint32_t xfs_dir2_da_hashname(const uint8_t *name, int namelen) } static void *get_dirblks(struct fs_info *fs, block_t startblock, - xfs_filblks_t c) + xfs_filblks_t c) { - int count = c << XFS_INFO(fs)->dirblklog; - uint8_t *p; - uint8_t *buf; - off_t offset = 0; + const size_t len = c * XFS_INFO(fs)->dirblksize; + uint64_t offs = startblock << BLOCK_SHIFT(fs); + void *buf; + size_t ret; - buf = malloc(c * XFS_INFO(fs)->dirblksize); + buf = malloc(len); if (!buf) malloc_error("buffer memory"); + memset(buf, 0, len); - memset(buf, 0, XFS_INFO(fs)->dirblksize); - - while (count--) { - p = (uint8_t *)get_cache(fs->fs_dev, startblock++); - memcpy(buf + offset, p, BLOCK_SIZE(fs)); - offset += BLOCK_SIZE(fs); + ret = cache_read(fs, buf, offs, len); + if (ret != len) { + xfs_error("failed to read contiguous directory blocks\n"); + free(buf); + return NULL; } - return buf; } -const void *xfs_dir2_dirblks_get_cached(struct fs_info *fs, block_t startblock, - xfs_filblks_t c) +void *xfs_dir2_dirblks_get_cached(struct fs_info *fs, block_t startblock, + xfs_filblks_t c) { unsigned char i; void *buf; @@ -100,6 +99,8 @@ const void *xfs_dir2_dirblks_get_cached(struct fs_info *fs, block_t startblock, if (!dirblks_cached_count) { buf = get_dirblks(fs, startblock, c); + if (!buf) + return NULL; dirblks_cache[dirblks_cached_count].dc_startblock = startblock; dirblks_cache[dirblks_cached_count].dc_blkscount = c; @@ -116,6 +117,8 @@ const void *xfs_dir2_dirblks_get_cached(struct fs_info *fs, block_t startblock, } buf = get_dirblks(fs, startblock, c); + if (!buf) + return NULL; dirblks_cache[XFS_DIR2_DIRBLKS_CACHE_SIZE / 2].dc_startblock = startblock; @@ -144,6 +147,8 @@ const void *xfs_dir2_dirblks_get_cached(struct fs_info *fs, block_t startblock, } buf = get_dirblks(fs, startblock, c); + if (!buf) + return NULL; dirblks_cache[dirblks_cached_count].dc_startblock = startblock; dirblks_cache[dirblks_cached_count].dc_blkscount = c; @@ -152,7 +157,6 @@ const void *xfs_dir2_dirblks_get_cached(struct fs_info *fs, block_t startblock, return dirblks_cache[dirblks_cached_count++].dc_area; } } - return NULL; } @@ -171,23 +175,27 @@ void xfs_dir2_dirblks_flush_cache(void) struct inode *xfs_dir2_local_find_entry(const char *dname, struct inode *parent, xfs_dinode_t *core) { - xfs_dir2_sf_t *sf = (xfs_dir2_sf_t *)&core->di_literal_area[0]; + xfs_dir2_sf_t *sf = XFS_DFORK_PTR(core, XFS_DATA_FORK); xfs_dir2_sf_entry_t *sf_entry; + uint8_t ftypelen = core->di_version == 3 ? 1 : 0; uint8_t count = sf->hdr.i8count ? sf->hdr.i8count : sf->hdr.count; struct fs_info *fs = parent->fs; struct inode *inode; + xfs_dir2_inou_t *inou; xfs_intino_t ino; xfs_dinode_t *ncore = NULL; xfs_debug("dname %s parent %p core %p", dname, parent, core); xfs_debug("count %hhu i8count %hhu", sf->hdr.count, sf->hdr.i8count); - sf_entry = (xfs_dir2_sf_entry_t *)((uint8_t *)&sf->list[0] - + sf_entry = (xfs_dir2_sf_entry_t *)((uint8_t *)sf->list - (!sf->hdr.i8count ? 4 : 0)); while (count--) { - uint8_t *start_name = &sf_entry->name[0]; + uint8_t *start_name = sf_entry->name; uint8_t *end_name = start_name + sf_entry->namelen; + xfs_debug("namelen %u", sf_entry->namelen); + if (!xfs_dir2_entry_name_cmp(start_name, end_name, dname)) { xfs_debug("Found entry %s", dname); goto found; @@ -195,8 +203,9 @@ struct inode *xfs_dir2_local_find_entry(const char *dname, struct inode *parent, sf_entry = (xfs_dir2_sf_entry_t *)((uint8_t *)sf_entry + offsetof(struct xfs_dir2_sf_entry, - name[0]) + + name) + sf_entry->namelen + + ftypelen + (sf->hdr.i8count ? 8 : 4)); } @@ -205,11 +214,12 @@ struct inode *xfs_dir2_local_find_entry(const char *dname, struct inode *parent, found: inode = xfs_new_inode(fs); - ino = xfs_dir2_sf_get_inumber(sf, (xfs_dir2_inou_t *)( - (uint8_t *)sf_entry + - offsetof(struct xfs_dir2_sf_entry, - name[0]) + - sf_entry->namelen)); + inou = (xfs_dir2_inou_t *)((uint8_t *)sf_entry + + offsetof(struct xfs_dir2_sf_entry, + name) + + sf_entry->namelen + + ftypelen); + ino = xfs_dir2_sf_get_inumber(sf, inou); xfs_debug("entry inode's number %lu", ino); @@ -251,6 +261,7 @@ struct inode *xfs_dir2_block_find_entry(const char *dname, struct inode *parent, block_t dir_blk; struct fs_info *fs = parent->fs; const uint8_t *dirblk_buf; + bool isdir3; uint8_t *p, *endp; xfs_dir2_data_hdr_t *hdr; struct inode *inode = NULL; @@ -262,18 +273,26 @@ struct inode *xfs_dir2_block_find_entry(const char *dname, struct inode *parent, xfs_debug("dname %s parent %p core %p", dname, parent, core); - bmbt_irec_get(&r, (xfs_bmbt_rec_t *)&core->di_literal_area[0]); + bmbt_irec_get(&r, XFS_DFORK_PTR(core, XFS_DATA_FORK)); dir_blk = fsblock_to_bytes(fs, r.br_startblock) >> BLOCK_SHIFT(fs); dirblk_buf = xfs_dir2_dirblks_get_cached(fs, dir_blk, r.br_blockcount); + if (!dirblk_buf) + return NULL; + hdr = (xfs_dir2_data_hdr_t *)dirblk_buf; - if (be32_to_cpu(hdr->magic) != XFS_DIR2_BLOCK_MAGIC) { + if (be32_to_cpu(hdr->magic) == XFS_DIR2_BLOCK_MAGIC) { + isdir3 = false; + } else if (be32_to_cpu(hdr->magic) == XFS_DIR3_BLOCK_MAGIC) { + isdir3 = true; + } else { xfs_error("Block directory header's magic number does not match!"); xfs_debug("hdr->magic: 0x%lx", be32_to_cpu(hdr->magic)); goto out; } - p = (uint8_t *)(hdr + 1); + p = (uint8_t *)dirblk_buf + (isdir3 ? sizeof(struct xfs_dir3_data_hdr) : + sizeof(struct xfs_dir2_data_hdr)); btp = xfs_dir2_block_tail_p(XFS_INFO(fs), hdr); endp = (uint8_t *)((xfs_dir2_leaf_entry_t *)btp - be32_to_cpu(btp->count)); @@ -290,7 +309,7 @@ struct inode *xfs_dir2_block_find_entry(const char *dname, struct inode *parent, dep = (xfs_dir2_data_entry_t *)p; - start_name = &dep->name[0]; + start_name = dep->name; end_name = start_name + dep->namelen; if (!xfs_dir2_entry_name_cmp(start_name, end_name, dname)) { @@ -298,7 +317,8 @@ struct inode *xfs_dir2_block_find_entry(const char *dname, struct inode *parent, goto found; } - p += xfs_dir2_data_entsize(dep->namelen); + p += (isdir3 ? xfs_dir3_data_entsize(dep->namelen) : + xfs_dir2_data_entsize(dep->namelen)); } out: @@ -348,7 +368,9 @@ failed: struct inode *xfs_dir2_leaf_find_entry(const char *dname, struct inode *parent, xfs_dinode_t *core) { - xfs_dir2_leaf_t *leaf; + xfs_dir2_leaf_hdr_t *hdr; + xfs_dir2_leaf_entry_t *ents; + uint16_t count; xfs_bmbt_irec_t irec; block_t leaf_blk, dir_blk; xfs_dir2_leaf_entry_t *lep; @@ -358,37 +380,47 @@ struct inode *xfs_dir2_leaf_find_entry(const char *dname, struct inode *parent, uint32_t hash = 0; uint32_t hashwant; uint32_t newdb, curdb = -1; - xfs_dir2_data_entry_t *dep; + xfs_dir2_data_entry_t *dep = NULL; struct inode *ip; xfs_dir2_data_hdr_t *data_hdr; uint8_t *start_name; uint8_t *end_name; xfs_intino_t ino; xfs_dinode_t *ncore; - const uint8_t *buf = NULL; + uint8_t *buf = NULL; xfs_debug("dname %s parent %p core %p", dname, parent, core); - bmbt_irec_get(&irec, ((xfs_bmbt_rec_t *)&core->di_literal_area[0]) + + bmbt_irec_get(&irec, (xfs_bmbt_rec_t *)XFS_DFORK_PTR(core, XFS_DATA_FORK) + be32_to_cpu(core->di_nextents) - 1); leaf_blk = fsblock_to_bytes(parent->fs, irec.br_startblock) >> BLOCK_SHIFT(parent->fs); - leaf = (xfs_dir2_leaf_t *)xfs_dir2_dirblks_get_cached(parent->fs, leaf_blk, - irec.br_blockcount); - if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR2_LEAF1_MAGIC) { + hdr = xfs_dir2_dirblks_get_cached(parent->fs, leaf_blk, + irec.br_blockcount); + if (!hdr) + return NULL; + + if (be16_to_cpu(hdr->info.magic) == XFS_DIR2_LEAF1_MAGIC) { + count = be16_to_cpu(hdr->count); + ents = (xfs_dir2_leaf_entry_t *)((uint8_t *)hdr + + sizeof(struct xfs_dir2_leaf_hdr)); + } else if (be16_to_cpu(hdr->info.magic) == XFS_DIR3_LEAF1_MAGIC) { + count = be16_to_cpu(((xfs_dir3_leaf_hdr_t *)hdr)->count); + ents = (xfs_dir2_leaf_entry_t *)((uint8_t *)hdr + + sizeof(struct xfs_dir3_leaf_hdr)); + } else { xfs_error("Single leaf block header's magic number does not match!"); goto out; } - if (!leaf->hdr.count) + if (!count) goto out; hashwant = xfs_dir2_da_hashname((uint8_t *)dname, strlen(dname)); /* Binary search */ - for (lep = leaf->ents, low = 0, high = be16_to_cpu(leaf->hdr.count) - 1; - low <= high; ) { + for (lep = ents, low = 0, high = count - 1; low <= high; ) { mid = (low + high) >> 1; if ((hash = be32_to_cpu(lep[mid].hashval)) == hashwant) break; @@ -407,10 +439,8 @@ struct inode *xfs_dir2_leaf_find_entry(const char *dname, struct inode *parent, while (mid > 0 && be32_to_cpu(lep[mid - 1].hashval) == hashwant) mid--; - for (lep = &leaf->ents[mid]; - mid < be16_to_cpu(leaf->hdr.count) && - be32_to_cpu(lep->hashval) == hashwant; - lep++, mid++) { + for (lep = &ents[mid]; + mid < count && be32_to_cpu(lep->hashval) == hashwant; lep++, mid++) { /* Skip over stale leaf entries. */ if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR) continue; @@ -418,13 +448,17 @@ struct inode *xfs_dir2_leaf_find_entry(const char *dname, struct inode *parent, newdb = xfs_dir2_dataptr_to_db(parent->fs, be32_to_cpu(lep->address)); if (newdb != curdb) { bmbt_irec_get(&irec, - ((xfs_bmbt_rec_t *)&core->di_literal_area[0]) + newdb); + (xfs_bmbt_rec_t *)XFS_DFORK_PTR(core, + XFS_DATA_FORK) + + newdb); dir_blk = fsblock_to_bytes(parent->fs, irec.br_startblock) >> BLOCK_SHIFT(parent->fs); - buf = xfs_dir2_dirblks_get_cached(parent->fs, dir_blk, irec.br_blockcount); + buf = xfs_dir2_dirblks_get_cached(parent->fs, dir_blk, + irec.br_blockcount); data_hdr = (xfs_dir2_data_hdr_t *)buf; - if (be32_to_cpu(data_hdr->magic) != XFS_DIR2_DATA_MAGIC) { + if (be32_to_cpu(data_hdr->magic) != XFS_DIR2_DATA_MAGIC && + be32_to_cpu(data_hdr->magic) != XFS_DIR3_DATA_MAGIC) { xfs_error("Leaf directory's data magic No. does not match!"); goto out; } @@ -432,10 +466,10 @@ struct inode *xfs_dir2_leaf_find_entry(const char *dname, struct inode *parent, curdb = newdb; } - dep = (xfs_dir2_data_entry_t *)((char *)buf + - xfs_dir2_dataptr_to_off(parent->fs, be32_to_cpu(lep->address))); - - start_name = &dep->name[0]; + dep = (xfs_dir2_data_entry_t *)( + buf + xfs_dir2_dataptr_to_off(parent->fs, + be32_to_cpu(lep->address))); + start_name = dep->name; end_name = start_name + dep->namelen; if (!xfs_dir2_entry_name_cmp(start_name, end_name, dname)) { @@ -523,7 +557,7 @@ block_t xfs_dir2_get_right_blk(struct fs_info *fs, xfs_dinode_t *core, int nextents; xfs_bmbt_ptr_t *pp; xfs_bmbt_key_t *kp; - xfs_btree_block_t *blk; + const xfs_btree_block_t *blk; xfs_bmbt_rec_t *xp; *error = 0; @@ -531,7 +565,8 @@ block_t xfs_dir2_get_right_blk(struct fs_info *fs, xfs_dinode_t *core, xfs_debug("XFS_DINODE_FMT_EXTENTS"); for (idx = 0; idx < be32_to_cpu(core->di_nextents); idx++) { bmbt_irec_get(&irec, - ((xfs_bmbt_rec_t *)&core->di_literal_area[0]) + idx); + (xfs_bmbt_rec_t *) + XFS_DFORK_PTR(core, XFS_DATA_FORK) + idx); if (fsblkno >= irec.br_startoff && fsblkno < irec.br_startoff + irec.br_blockcount) break; @@ -539,7 +574,7 @@ block_t xfs_dir2_get_right_blk(struct fs_info *fs, xfs_dinode_t *core, } else if (core->di_format == XFS_DINODE_FMT_BTREE) { xfs_debug("XFS_DINODE_FMT_BTREE"); bno = NULLFSBLOCK; - rblock = (xfs_bmdr_block_t *)&core->di_literal_area[0]; + rblock = XFS_DFORK_PTR(core, XFS_DATA_FORK); fsize = XFS_DFORK_SIZE(core, fs, XFS_DATA_FORK); pp = XFS_BMDR_PTR_ADDR(rblock, 1, xfs_bmdr_maxrecs(fsize, 0)); kp = XFS_BMDR_KEY_ADDR(rblock, 1); @@ -549,7 +584,7 @@ block_t xfs_dir2_get_right_blk(struct fs_info *fs, xfs_dinode_t *core, /* Find the leaf */ for (;;) { - blk = (xfs_btree_block_t *)get_cache(fs->fs_dev, bno); + blk = get_cache(fs->fs_dev, bno); if (be16_to_cpu(blk->bb_level) == 0) break; pp = XFS_BMBT_PTR_ADDR(fs, blk, 1, @@ -576,7 +611,7 @@ block_t xfs_dir2_get_right_blk(struct fs_info *fs, xfs_dinode_t *core, if (nextbno == NULLFSBLOCK) break; bno = fsblock_to_bytes(fs, nextbno) >> BLOCK_SHIFT(fs); - blk = (xfs_btree_block_t *)get_cache(fs->fs_dev, bno); + blk = get_cache(fs->fs_dev, bno); } } @@ -593,110 +628,99 @@ struct inode *xfs_dir2_node_find_entry(const char *dname, struct inode *parent, xfs_dinode_t *core) { block_t fsblkno; - xfs_da_intnode_t *node = NULL; + xfs_da_node_hdr_t *nhdr; uint32_t hashwant; uint32_t hash = 0; + uint16_t i; + uint16_t count; xfs_da_node_entry_t *btree; - uint16_t max; - uint16_t span; - uint16_t probe; int error; + xfs_dir2_leaf_hdr_t *lhdr; xfs_dir2_data_hdr_t *data_hdr; - xfs_dir2_leaf_t *leaf; xfs_dir2_leaf_entry_t *lep; xfs_dir2_data_entry_t *dep; + xfs_dir2_leaf_entry_t *ents; struct inode *ip; uint8_t *start_name; uint8_t *end_name; int low; int high; int mid = 0; - uint32_t newdb, curdb = -1; + uint32_t newdb; + uint32_t curdb; xfs_intino_t ino; xfs_dinode_t *ncore; - const uint8_t *buf = NULL; + uint8_t *buf = NULL; xfs_debug("dname %s parent %p core %p", dname, parent, core); - hashwant = xfs_dir2_da_hashname((uint8_t *)dname, strlen(dname)); - - fsblkno = xfs_dir2_get_right_blk(parent->fs, core, - xfs_dir2_byte_to_db(parent->fs, XFS_DIR2_LEAF_OFFSET), - &error); + curdb = xfs_dir2_byte_to_db(parent->fs, XFS_DIR2_LEAF_OFFSET); + fsblkno = xfs_dir2_get_right_blk(parent->fs, core, curdb, &error); if (error) { xfs_error("Cannot find right rec!"); return NULL; } - node = (xfs_da_intnode_t *)xfs_dir2_dirblks_get_cached(parent->fs, fsblkno, - 1); - if (be16_to_cpu(node->hdr.info.magic) != XFS_DA_NODE_MAGIC) { - xfs_error("Node's magic number does not match!"); + nhdr = xfs_dir2_dirblks_get_cached(parent->fs, fsblkno, 1); + if (be16_to_cpu(nhdr->info.magic) == XFS_DA_NODE_MAGIC) { + count = be16_to_cpu(nhdr->count); + btree = (xfs_da_node_entry_t *)((uint8_t *)nhdr + + sizeof(struct xfs_da_node_hdr)); + } else if (be16_to_cpu(nhdr->info.magic) == XFS_DA3_NODE_MAGIC) { + count = be16_to_cpu(((xfs_da3_node_hdr_t *)nhdr)->count); + btree = (xfs_da_node_entry_t *)((uint8_t *)nhdr + + sizeof(struct xfs_da3_node_hdr)); + } else { + xfs_error("Node's magic number (0x%04x) does not match!"); goto out; } - do { - if (!node->hdr.count) - goto out; - - /* Given a hash to lookup, you read the node's btree array and first - * "hashval" in the array that exceeds the given hash and it can then - * be found in the block pointed by the "before" value. - */ - max = be16_to_cpu(node->hdr.count); - - probe = span = max/2; - for (btree = &node->btree[probe]; - span > 4; btree = &node->btree[probe]) { - span /= 2; - hash = be32_to_cpu(btree->hashval); - - if (hash < hashwant) - probe += span; - else if (hash > hashwant) - probe -= span; - else - break; - } - - while ((probe > 0) && (be32_to_cpu(btree->hashval) >= hashwant)) { - btree--; - probe--; - } - - while ((probe < max) && (be32_to_cpu(btree->hashval) < hashwant)) { - btree++; - probe++; - } + hashwant = xfs_dir2_da_hashname((uint8_t *)dname, strlen(dname)); - if (probe == max) - fsblkno = be32_to_cpu(node->btree[max-1].before); - else - fsblkno = be32_to_cpu(node->btree[probe].before); + /* Given a hash to lookup, you read the node's btree array and first + * "hashval" in the array that exceeds the given hash and it can then + * be found in the block pointed by the "before" value. + */ + fsblkno = 0; + for (i = 0; i < count; i++) { + if (hashwant < be32_to_cpu(btree[i].hashval)) { + fsblkno = be32_to_cpu(btree[i].before); + break; + } + } - fsblkno = xfs_dir2_get_right_blk(parent->fs, core, fsblkno, &error); - if (error) { - xfs_error("Cannot find right rec!"); - goto out; - } + if (!fsblkno) + goto out; - node = (xfs_da_intnode_t *)xfs_dir2_dirblks_get_cached(parent->fs, - fsblkno, 1); - } while(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); + fsblkno = xfs_dir2_get_right_blk(parent->fs, core, fsblkno, &error); + if (error) { + xfs_error("Cannot find leaf record"); + goto out; + } - leaf = (xfs_dir2_leaf_t*)node; - if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR2_LEAFN_MAGIC) { - xfs_error("Leaf's magic number does not match!"); + lhdr = xfs_dir2_dirblks_get_cached(parent->fs, fsblkno, 1); + if (be16_to_cpu(lhdr->info.magic) == XFS_DIR2_LEAFN_MAGIC) { + count = be16_to_cpu(lhdr->count); + ents = (xfs_dir2_leaf_entry_t *)((uint8_t *)lhdr + + sizeof(struct xfs_dir2_leaf_hdr)); + } else if (be16_to_cpu(lhdr->info.magic) == XFS_DIR3_LEAFN_MAGIC) { + count = be16_to_cpu(((xfs_dir3_leaf_hdr_t *)lhdr)->count); + ents = (xfs_dir2_leaf_entry_t *)((uint8_t *)lhdr + + sizeof(struct xfs_dir3_leaf_hdr)); + } else { + xfs_error("Leaf's magic number does not match (0x%04x)!", + be16_to_cpu(lhdr->info.magic)); goto out; } - if (!leaf->hdr.count) - goto out; + if (!count) + goto out; - for (lep = leaf->ents, low = 0, high = be16_to_cpu(leaf->hdr.count) - 1; - low <= high; ) { + lep = ents; + low = 0; + high = count - 1; + while (low <= high) { mid = (low + high) >> 1; - if ((hash = be32_to_cpu(lep[mid].hashval)) == hashwant) break; if (hash < hashwant) @@ -714,9 +738,8 @@ struct inode *xfs_dir2_node_find_entry(const char *dname, struct inode *parent, while (mid > 0 && be32_to_cpu(lep[mid - 1].hashval) == hashwant) mid--; - for (lep = &leaf->ents[mid]; - mid < be16_to_cpu(leaf->hdr.count) && - be32_to_cpu(lep->hashval) == hashwant; + curdb = -1; + for (lep = &ents[mid]; mid < count && be32_to_cpu(lep->hashval) == hashwant; lep++, mid++) { /* Skip over stale leaf entries. */ if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR) @@ -732,7 +755,8 @@ struct inode *xfs_dir2_node_find_entry(const char *dname, struct inode *parent, buf = xfs_dir2_dirblks_get_cached(parent->fs, fsblkno, 1); data_hdr = (xfs_dir2_data_hdr_t *)buf; - if (be32_to_cpu(data_hdr->magic) != XFS_DIR2_DATA_MAGIC) { + if (be32_to_cpu(data_hdr->magic) != XFS_DIR2_DATA_MAGIC && + be32_to_cpu(data_hdr->magic) != XFS_DIR3_DATA_MAGIC) { xfs_error("Leaf directory's data magic No. does not match!"); goto out; } @@ -740,10 +764,10 @@ struct inode *xfs_dir2_node_find_entry(const char *dname, struct inode *parent, curdb = newdb; } - dep = (xfs_dir2_data_entry_t *)((char *)buf + - xfs_dir2_dataptr_to_off(parent->fs, be32_to_cpu(lep->address))); - - start_name = &dep->name[0]; + dep = (xfs_dir2_data_entry_t *)( + buf + xfs_dir2_dataptr_to_off(parent->fs, + be32_to_cpu(lep->address))); + start_name = dep->name; end_name = start_name + dep->namelen; if (!xfs_dir2_entry_name_cmp(start_name, end_name, dname)) { diff --git a/core/fs/xfs/xfs_dir2.h b/core/fs/xfs/xfs_dir2.h index 158cf44f..1e1fb579 100644 --- a/core/fs/xfs/xfs_dir2.h +++ b/core/fs/xfs/xfs_dir2.h @@ -23,8 +23,8 @@ #include "xfs.h" -const void *xfs_dir2_dirblks_get_cached(struct fs_info *fs, block_t startblock, - xfs_filblks_t c); +void *xfs_dir2_dirblks_get_cached(struct fs_info *fs, block_t startblock, + xfs_filblks_t c); void xfs_dir2_dirblks_flush_cache(void); uint32_t xfs_dir2_da_hashname(const uint8_t *name, int namelen); @@ -46,7 +46,7 @@ static inline bool xfs_dir2_isleaf(struct fs_info *fs, xfs_dinode_t *dip) uint64_t last = 0; xfs_bmbt_irec_t irec; - bmbt_irec_get(&irec, ((xfs_bmbt_rec_t *)&dip->di_literal_area[0]) + + bmbt_irec_get(&irec, (xfs_bmbt_rec_t *)XFS_DFORK_PTR(dip, XFS_DATA_FORK) + be32_to_cpu(dip->di_nextents) - 1); last = irec.br_startoff + irec.br_blockcount; diff --git a/core/fs/xfs/xfs_readdir.c b/core/fs/xfs/xfs_readdir.c index 86c8a77b..51518ef6 100644 --- a/core/fs/xfs/xfs_readdir.c +++ b/core/fs/xfs/xfs_readdir.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 Paulo Alcantara <pcacjr@zytor.com> + * Copyright (c) 2012-2015 Paulo Alcantara <pcacjr@zytor.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -64,10 +64,12 @@ static int fill_dirent(struct fs_info *fs, struct dirent *dirent, int xfs_readdir_dir2_local(struct file *file, struct dirent *dirent, xfs_dinode_t *core) { - xfs_dir2_sf_t *sf = (xfs_dir2_sf_t *)&core->di_literal_area[0]; + xfs_dir2_sf_t *sf = XFS_DFORK_PTR(core, XFS_DATA_FORK); xfs_dir2_sf_entry_t *sf_entry; + uint8_t ftypelen = core->di_version == 3 ? 1 : 0; uint8_t count = sf->hdr.i8count ? sf->hdr.i8count : sf->hdr.count; uint32_t offset = file->offset; + xfs_dir2_inou_t *inou; uint8_t *start_name; uint8_t *end_name; xfs_ino_t ino; @@ -82,7 +84,7 @@ int xfs_readdir_dir2_local(struct file *file, struct dirent *dirent, file->offset++; - sf_entry = (xfs_dir2_sf_entry_t *)((uint8_t *)&sf->list[0] - + sf_entry = (xfs_dir2_sf_entry_t *)((uint8_t *)sf->list - (!sf->hdr.i8count ? 4 : 0)); if (file->offset - 1) { @@ -91,20 +93,22 @@ int xfs_readdir_dir2_local(struct file *file, struct dirent *dirent, sf_entry = (xfs_dir2_sf_entry_t *)( (uint8_t *)sf_entry + offsetof(struct xfs_dir2_sf_entry, - name[0]) + + name) + sf_entry->namelen + + ftypelen + (sf->hdr.i8count ? 8 : 4)); } } - start_name = &sf_entry->name[0]; + start_name = sf_entry->name; end_name = start_name + sf_entry->namelen; - ino = xfs_dir2_sf_get_inumber(sf, (xfs_dir2_inou_t *)( - (uint8_t *)sf_entry + - offsetof(struct xfs_dir2_sf_entry, - name[0]) + - sf_entry->namelen)); + inou = (xfs_dir2_inou_t *)((uint8_t *)sf_entry + + offsetof(struct xfs_dir2_sf_entry, + name) + + sf_entry->namelen + + ftypelen); + ino = xfs_dir2_sf_get_inumber(sf, inou); retval = fill_dirent(fs, dirent, file->offset, ino, (char *)start_name, end_name - start_name); @@ -126,6 +130,7 @@ int xfs_readdir_dir2_block(struct file *file, struct dirent *dirent, block_t dir_blk; struct fs_info *fs = file->fs; const uint8_t *dirblk_buf; + bool isdir3; uint8_t *p; uint32_t offset; xfs_dir2_data_hdr_t *hdr; @@ -139,12 +144,16 @@ int xfs_readdir_dir2_block(struct file *file, struct dirent *dirent, xfs_debug("file %p dirent %p core %p", file, dirent, core); - bmbt_irec_get(&r, (xfs_bmbt_rec_t *)&core->di_literal_area[0]); + bmbt_irec_get(&r, XFS_DFORK_PTR(core, XFS_DATA_FORK)); dir_blk = fsblock_to_bytes(fs, r.br_startblock) >> BLOCK_SHIFT(fs); dirblk_buf = xfs_dir2_dirblks_get_cached(fs, dir_blk, r.br_blockcount); hdr = (xfs_dir2_data_hdr_t *)dirblk_buf; - if (be32_to_cpu(hdr->magic) != XFS_DIR2_BLOCK_MAGIC) { + if (be32_to_cpu(hdr->magic) == XFS_DIR2_BLOCK_MAGIC) { + isdir3 = false; + } else if (be32_to_cpu(hdr->magic) == XFS_DIR3_BLOCK_MAGIC) { + isdir3 = true; + } else { xfs_error("Block directory header's magic number does not match!"); xfs_debug("hdr->magic: 0x%lx", be32_to_cpu(hdr->magic)); goto out; @@ -157,7 +166,8 @@ int xfs_readdir_dir2_block(struct file *file, struct dirent *dirent, file->offset++; - p = (uint8_t *)(hdr + 1); + p = (uint8_t *)dirblk_buf + (isdir3 ? sizeof(struct xfs_dir3_data_hdr) : + sizeof(struct xfs_dir2_data_hdr)); if (file->offset - 1) { offset = file->offset; @@ -170,7 +180,8 @@ int xfs_readdir_dir2_block(struct file *file, struct dirent *dirent, continue; } - p += xfs_dir2_data_entsize(dep->namelen); + p += (isdir3 ? xfs_dir3_data_entsize(dep->namelen) : + xfs_dir2_data_entsize(dep->namelen)); } } @@ -197,9 +208,11 @@ out: int xfs_readdir_dir2_leaf(struct file *file, struct dirent *dirent, xfs_dinode_t *core) { + xfs_dir2_leaf_hdr_t *hdr; + xfs_dir2_leaf_entry_t *ents; + uint16_t count; xfs_bmbt_irec_t irec; struct fs_info *fs = file->fs; - xfs_dir2_leaf_t *leaf; block_t leaf_blk, dir_blk; xfs_dir2_leaf_entry_t *lep; uint32_t db; @@ -214,39 +227,49 @@ int xfs_readdir_dir2_leaf(struct file *file, struct dirent *dirent, xfs_debug("file %p dirent %p core %p", file, dirent, core); - bmbt_irec_get(&irec, ((xfs_bmbt_rec_t *)&core->di_literal_area[0]) + + bmbt_irec_get(&irec, (xfs_bmbt_rec_t *)XFS_DFORK_PTR(core, XFS_DATA_FORK) + be32_to_cpu(core->di_nextents) - 1); leaf_blk = fsblock_to_bytes(fs, irec.br_startblock) >> BLOCK_SHIFT(file->fs); - leaf = (xfs_dir2_leaf_t *)xfs_dir2_dirblks_get_cached(fs, leaf_blk, - irec.br_blockcount); - if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR2_LEAF1_MAGIC) { + hdr = xfs_dir2_dirblks_get_cached(fs, leaf_blk, irec.br_blockcount); + if (!hdr) + return -1; + + if (be16_to_cpu(hdr->info.magic) == XFS_DIR2_LEAF1_MAGIC) { + count = be16_to_cpu(hdr->count); + ents = (xfs_dir2_leaf_entry_t *)((uint8_t *)hdr + + sizeof(struct xfs_dir2_leaf_hdr)); + } else if (be16_to_cpu(hdr->info.magic) == XFS_DIR3_LEAF1_MAGIC) { + count = be16_to_cpu(((xfs_dir3_leaf_hdr_t *)hdr)->count); + ents = (xfs_dir2_leaf_entry_t *)((uint8_t *)hdr + + sizeof(struct xfs_dir3_leaf_hdr)); + } else { xfs_error("Single leaf block header's magic number does not match!"); goto out; } - if (!leaf->hdr.count) - goto out; - - if (file->offset + 1 > be16_to_cpu(leaf->hdr.count)) + if (!count || file->offset + 1 > count) goto out; - lep = &leaf->ents[file->offset++]; + lep = &ents[file->offset++]; /* Skip over stale leaf entries */ for ( ; be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR; - lep++, file->offset++); + lep++, file->offset++) + ; db = xfs_dir2_dataptr_to_db(fs, be32_to_cpu(lep->address)); - bmbt_irec_get(&irec, (xfs_bmbt_rec_t *)&core->di_literal_area[0] + db); + bmbt_irec_get(&irec, (xfs_bmbt_rec_t *)XFS_DFORK_PTR(core, + XFS_DATA_FORK) + db); dir_blk = fsblock_to_bytes(fs, irec.br_startblock) >> BLOCK_SHIFT(fs); buf = xfs_dir2_dirblks_get_cached(fs, dir_blk, irec.br_blockcount); data_hdr = (xfs_dir2_data_hdr_t *)buf; - if (be32_to_cpu(data_hdr->magic) != XFS_DIR2_DATA_MAGIC) { + if (be32_to_cpu(data_hdr->magic) != XFS_DIR2_DATA_MAGIC && + be32_to_cpu(data_hdr->magic) != XFS_DIR3_DATA_MAGIC) { xfs_error("Leaf directory's data magic number does not match!"); goto out; } @@ -277,14 +300,16 @@ int xfs_readdir_dir2_node(struct file *file, struct dirent *dirent, xfs_dinode_t *core) { struct fs_info *fs = file->fs; - xfs_bmbt_irec_t irec; - uint32_t node_off = 0; block_t fsblkno; - xfs_da_intnode_t *node = NULL; + xfs_da_node_hdr_t *nhdr; + xfs_da_node_entry_t *btree; + uint16_t btcount; + uint16_t lfcount; + xfs_dir2_leaf_hdr_t *lhdr; + xfs_dir2_leaf_entry_t *ents; struct inode *inode = file->inode; int error; xfs_dir2_data_hdr_t *data_hdr; - xfs_dir2_leaf_t *leaf; xfs_dir2_leaf_entry_t *lep; unsigned int offset; xfs_dir2_data_entry_t *dep; @@ -296,52 +321,71 @@ int xfs_readdir_dir2_node(struct file *file, struct dirent *dirent, xfs_debug("file %p dirent %p core %p", file, dirent, core); - do { - bmbt_irec_get(&irec, (xfs_bmbt_rec_t *)&core->di_literal_area[0] + - ++node_off); - } while (irec.br_startoff < xfs_dir2_byte_to_db(fs, XFS_DIR2_LEAF_OFFSET)); - - fsblkno = fsblock_to_bytes(fs, irec.br_startblock) >> BLOCK_SHIFT(fs); + db = xfs_dir2_byte_to_db(fs, XFS_DIR2_LEAF_OFFSET); + fsblkno = xfs_dir2_get_right_blk(fs, core, db, &error); + if (error) { + xfs_error("Cannot find fs block"); + return -1; + } - node = (xfs_da_intnode_t *)xfs_dir2_dirblks_get_cached(fs, fsblkno, 1); - if (be16_to_cpu(node->hdr.info.magic) != XFS_DA_NODE_MAGIC) { - xfs_error("Node's magic number does not match!"); + nhdr = xfs_dir2_dirblks_get_cached(fs, fsblkno, 1); + if (be16_to_cpu(nhdr->info.magic) == XFS_DA_NODE_MAGIC) { + btcount = be16_to_cpu(nhdr->count); + btree = (xfs_da_node_entry_t *)((uint8_t *)nhdr + + sizeof(struct xfs_da_node_hdr)); + } else if (be16_to_cpu(nhdr->info.magic) == XFS_DA3_NODE_MAGIC) { + btcount = be16_to_cpu(((xfs_da3_node_hdr_t *)nhdr)->count); + btree = (xfs_da_node_entry_t *)((uint8_t *)nhdr + + sizeof(struct xfs_da3_node_hdr)); + } else { + xfs_error("Node's magic number (0x%04x) does not match!", + be16_to_cpu(nhdr->info.magic)); goto out; } try_next_btree: - if (!node->hdr.count || - XFS_PVT(inode)->i_btree_offset >= be16_to_cpu(node->hdr.count)) + if (!btcount || + XFS_PVT(inode)->i_btree_offset >= btcount) goto out; - fsblkno = be32_to_cpu(node->btree[XFS_PVT(inode)->i_btree_offset].before); + fsblkno = be32_to_cpu(btree[XFS_PVT(inode)->i_btree_offset].before); fsblkno = xfs_dir2_get_right_blk(fs, core, fsblkno, &error); if (error) { xfs_error("Cannot find leaf rec!"); goto out; } - leaf = (xfs_dir2_leaf_t*)xfs_dir2_dirblks_get_cached(fs, fsblkno, 1); - if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR2_LEAFN_MAGIC) { - xfs_error("Leaf's magic number does not match!"); + lhdr = xfs_dir2_dirblks_get_cached(fs, fsblkno, 1); + if (be16_to_cpu(lhdr->info.magic) == XFS_DIR2_LEAFN_MAGIC) { + lfcount = be16_to_cpu(lhdr->count); + ents = (xfs_dir2_leaf_entry_t *)((uint8_t *)lhdr + + sizeof(struct xfs_dir2_leaf_hdr)); + } else if (be16_to_cpu(lhdr->info.magic) == XFS_DIR3_LEAFN_MAGIC) { + lfcount = be16_to_cpu(((xfs_dir3_leaf_hdr_t *)lhdr)->count); + ents = (xfs_dir2_leaf_entry_t *)((uint8_t *)lhdr + + sizeof(struct xfs_dir3_leaf_hdr)); + } else { + xfs_error("Leaf's magic number does not match (0x%04x)!", + be16_to_cpu(lhdr->info.magic)); goto out; } - if (!leaf->hdr.count || - XFS_PVT(inode)->i_leaf_ent_offset >= be16_to_cpu(leaf->hdr.count)) { + if (!lfcount || + XFS_PVT(inode)->i_leaf_ent_offset >= lfcount) { XFS_PVT(inode)->i_btree_offset++; XFS_PVT(inode)->i_leaf_ent_offset = 0; goto try_next_btree; } - lep = &leaf->ents[XFS_PVT(inode)->i_leaf_ent_offset]; + lep = &ents[XFS_PVT(inode)->i_leaf_ent_offset]; /* Skip over stale leaf entries */ - for ( ; XFS_PVT(inode)->i_leaf_ent_offset < be16_to_cpu(leaf->hdr.count) && + for ( ; XFS_PVT(inode)->i_leaf_ent_offset < lfcount && be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR; - lep++, XFS_PVT(inode)->i_leaf_ent_offset++); + lep++, XFS_PVT(inode)->i_leaf_ent_offset++) + ; - if (XFS_PVT(inode)->i_leaf_ent_offset == be16_to_cpu(leaf->hdr.count)) { + if (XFS_PVT(inode)->i_leaf_ent_offset == lfcount) { XFS_PVT(inode)->i_btree_offset++; XFS_PVT(inode)->i_leaf_ent_offset = 0; goto try_next_btree; @@ -359,7 +403,8 @@ try_next_btree: buf = xfs_dir2_dirblks_get_cached(fs, fsblkno, 1); data_hdr = (xfs_dir2_data_hdr_t *)buf; - if (be32_to_cpu(data_hdr->magic) != XFS_DIR2_DATA_MAGIC) { + if (be32_to_cpu(data_hdr->magic) != XFS_DIR2_DATA_MAGIC && + be32_to_cpu(data_hdr->magic) != XFS_DIR3_DATA_MAGIC) { xfs_error("Leaf directory's data magic No. does not match!"); goto out; } diff --git a/core/i386/syslinux.ld b/core/i386/syslinux.ld index 7b4e012c..92b75b11 100644 --- a/core/i386/syslinux.ld +++ b/core/i386/syslinux.ld @@ -255,10 +255,9 @@ SECTIONS . = 0x100000; __pm_code_start = .; + __vma_to_lma = __pm_code_lma - __pm_code_start; - __text_vma = .; - __text_lma = __pm_code_lma; - .text : AT(__text_lma) { + .text : AT(ADDR(.text) + __vma_to_lma) { FILL(0x90909090) __text_start = .; *(.text) @@ -266,106 +265,68 @@ SECTIONS __text_end = .; } - . = ALIGN(16); - - __rodata_vma = .; - __rodata_lma = __rodata_vma + __text_lma - __text_vma; - .rodata : AT(__rodata_lma) { + .rodata : AT(ADDR(.rodata) + __vma_to_lma) { __rodata_start = .; *(.rodata) *(.rodata.*) __rodata_end = .; } - . = ALIGN(4); - - __ctors_vma = .; - __ctors_lma = __ctors_vma + __text_lma - __text_vma; - .ctors : AT(__ctors_lma) { + .ctors : AT(ADDR(.ctors) + __vma_to_lma) { __ctors_start = .; KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) __ctors_end = .; } - __dtors_vma = .; - __dtors_lma = __dtors_vma + __text_lma - __text_vma; - .dtors : AT(__dtors_lma) { + .dtors : AT(ADDR(.dtors) + __vma_to_lma) { __dtors_start = .; KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) __dtors_end = .; } - . = ALIGN(4); - - __dynsym_vma = .; - __dynsym_lma = __dynsym_vma + __text_lma - __text_vma; - .dynsym : AT(__dynsym_lma) { + .dynsym : AT(ADDR(.dynsym) + __vma_to_lma) { __dynsym_start = .; *(.dynsym) __dynsym_end = .; } __dynsym_len = __dynsym_end - __dynsym_start; - . = ALIGN(4); - - __dynstr_vma = .; - __dynstr_lma = __dynstr_vma + __text_lma - __text_vma; - .dynstr : AT(__dynstr_lma) { + .dynstr : AT(ADDR(.dynstr) + __vma_to_lma) { __dynstr_start = .; *(.dynstr) __dynstr_end = .; } __dynstr_len = __dynstr_end - __dynstr_start; - . = ALIGN(4); - - __gnu_hash_vma = .; - __gnu_hash_lma = __gnu_hash_vma + __text_lma - __text_vma; - .gnu.hash : AT(__gnu_hash_lma) { + .gnu.hash : AT(ADDR(.gnu.hash) + __vma_to_lma) { __gnu_hash_start = .; *(.gnu.hash) __gnu_hash_end = .; } - . = ALIGN(4); - - __dynlink_vma = .; - __dynlink_lma = __dynlink_vma + __text_lma - __text_vma; - .dynlink : AT(__dynlink_lma) { + .dynlink : AT(ADDR(.dynlink) + __vma_to_lma) { __dynlink_start = .; *(.dynlink) __dynlink_end = .; } - . = ALIGN(4); - - __got_vma = .; - __got_lma = __got_vma + __text_lma - __text_vma; - .got : AT(__got_lma) { + .got : AT(ADDR(.got) + __vma_to_lma) { __got_start = .; KEEP (*(.got.plt)) KEEP (*(.got)) __got_end = .; } - . = ALIGN(4); - - __dynamic_vma = .; - __dynamic_lma = __dynamic_vma + __text_lma - __text_vma; - .dynamic : AT(__dynamic_lma) { + .dynamic : AT(ADDR(.dynamic) + __vma_to_lma) { __dynamic_start = .; *(.dynamic) __dynamic_end = .; } - . = ALIGN(16); - - __data_vma = .; - __data_lma = __data_vma + __text_lma - __text_vma; - .data : AT(__data_lma) { + .data : AT(ADDR(.data) + __vma_to_lma) { __data_start = .; *(.data) *(.data.*) @@ -377,7 +338,7 @@ SECTIONS __pm_code_dwords = (__pm_code_len + 3) >> 2; . = ALIGN(128); - + __bss_vma = .; __bss_lma = .; /* Dummy */ .bss (NOLOAD) : AT (__bss_lma) { diff --git a/core/x86_64/syslinux.ld b/core/x86_64/syslinux.ld index 10571120..70c6e00a 100644 --- a/core/x86_64/syslinux.ld +++ b/core/x86_64/syslinux.ld @@ -255,10 +255,9 @@ SECTIONS . = 0x100000; __pm_code_start = .; + __vma_to_lma = __pm_code_lma - __pm_code_start; - __text_vma = .; - __text_lma = __pm_code_lma; - .text : AT(__text_lma) { + .text : AT(ADDR(.text) + __vma_to_lma) { FILL(0x90909090) __text_start = .; *(.text) @@ -266,106 +265,68 @@ SECTIONS __text_end = .; } - . = ALIGN(16); - - __rodata_vma = .; - __rodata_lma = __rodata_vma + __text_lma - __text_vma; - .rodata : AT(__rodata_lma) { + .rodata : AT(ADDR(.rodata) + __vma_to_lma) { __rodata_start = .; *(.rodata) *(.rodata.*) __rodata_end = .; } - . = ALIGN(4); - - __ctors_vma = .; - __ctors_lma = __ctors_vma + __text_lma - __text_vma; - .ctors : AT(__ctors_lma) { + .ctors : AT(ADDR(.ctors) + __vma_to_lma) { __ctors_start = .; KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) __ctors_end = .; } - __dtors_vma = .; - __dtors_lma = __dtors_vma + __text_lma - __text_vma; - .dtors : AT(__dtors_lma) { + .dtors : AT(ADDR(.dtors) + __vma_to_lma) { __dtors_start = .; KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) __dtors_end = .; } - . = ALIGN(4); - - __dynsym_vma = .; - __dynsym_lma = __dynsym_vma + __text_lma - __text_vma; - .dynsym : AT(__dynsym_lma) { + .dynsym : AT(ADDR(.dynsym) + __vma_to_lma) { __dynsym_start = .; *(.dynsym) __dynsym_end = .; } __dynsym_len = __dynsym_end - __dynsym_start; - . = ALIGN(4); - - __dynstr_vma = .; - __dynstr_lma = __dynstr_vma + __text_lma - __text_vma; - .dynstr : AT(__dynstr_lma) { + .dynstr : AT(ADDR(.dynstr) + __vma_to_lma) { __dynstr_start = .; *(.dynstr) __dynstr_end = .; } __dynstr_len = __dynstr_end - __dynstr_start; - . = ALIGN(4); - - __gnu_hash_vma = .; - __gnu_hash_lma = __gnu_hash_vma + __text_lma - __text_vma; - .gnu.hash : AT(__gnu_hash_lma) { + .gnu.hash : AT(ADDR(.gnu.hash) + __vma_to_lma) { __gnu_hash_start = .; *(.gnu.hash) __gnu_hash_end = .; } - . = ALIGN(4); - - __dynlink_vma = .; - __dynlink_lma = __dynlink_vma + __text_lma - __text_vma; - .dynlink : AT(__dynlink_lma) { + .dynlink : AT(ADDR(.dynlink) + __vma_to_lma) { __dynlink_start = .; *(.dynlink) __dynlink_end = .; } - . = ALIGN(4); - - __got_vma = .; - __got_lma = __got_vma + __text_lma - __text_vma; - .got : AT(__got_lma) { + .got : AT(ADDR(.got) + __vma_to_lma) { __got_start = .; KEEP (*(.got.plt)) KEEP (*(.got)) __got_end = .; } - . = ALIGN(4); - - __dynamic_vma = .; - __dynamic_lma = __dynamic_vma + __text_lma - __text_vma; - .dynamic : AT(__dynamic_lma) { + .dynamic : AT(ADDR(.dynamic) + __vma_to_lma) { __dynamic_start = .; *(.dynamic) __dynamic_end = .; } - . = ALIGN(16); - - __data_vma = .; - __data_lma = __data_vma + __text_lma - __text_vma; - .data : AT(__data_lma) { + .data : AT(ADDR(.data) + __vma_to_lma) { __data_start = .; *(.data) *(.data.*) @@ -377,7 +338,7 @@ SECTIONS __pm_code_dwords = (__pm_code_len + 3) >> 2; . = ALIGN(128); - + __bss_vma = .; __bss_lma = .; /* Dummy */ .bss (NOLOAD) : AT (__bss_lma) { diff --git a/diag/Makefile b/diag/Makefile index e3353753..619c1632 100644 --- a/diag/Makefile +++ b/diag/Makefile @@ -4,4 +4,4 @@ all tidy dist clean spotless install: @mkdir -p $(addprefix $(OBJ)/,$(SUBDIRS)) set -e; for d in $(SUBDIRS); \ do $(MAKE) -C $(OBJ)/$$d -f $(SRC)/$$d/Makefile \ - SRC="$(SRC)"/$$d OBJ="$(OBJ)"/$$d $@; done + SRC="$(SRC)"/$$d OBJ="$(OBJ)"/$$d EFI_BUILD=$(EFI_BUILD) $@; done @@ -83,7 +83,7 @@ int core_tcp_connect(struct pxe_pvt_inode *socket, uint32_t ip, uint16_t port) } } else { if (status != EFI_SUCCESS) - Print(L"core_tcp_connect: tcp->Configure() unsuccessful (%i)", status); + Print(L"core_tcp_connect: tcp->Configure() unsuccessful (%d)", status); unmapped = 0; } } @@ -18,6 +18,9 @@ extern EFI_GUID Udp4ServiceBindingProtocol, Udp4Protocol; */ static struct efi_binding *udp_reader; +static int volatile efi_udp_has_recv = 0; +int volatile efi_net_def_addr = 1; + /** * Try to configure this UDP socket * @@ -48,8 +51,11 @@ EFI_STATUS core_udp_configure(EFI_UDP4 *udp, EFI_UDP4_CONFIG_DATA *udata, unmapped = 0; } } else { - if (status != EFI_SUCCESS) - Print(L"%s: udp->Configure() unsuccessful (%i)", f, status); + if (status != EFI_SUCCESS) { + Print(L"%s: udp->Configure() unsuccessful (%d)", f, status); + if (!efi_net_def_addr && (status == EFI_INVALID_PARAMETER)) + efi_net_def_addr = 2; + } unmapped = 0; } } @@ -152,7 +158,13 @@ void core_udp_connect(struct pxe_pvt_inode *socket, uint32_t ip, /* Re-use the existing local port number */ udata.StationPort = socket->net.efi.localport; - udata.UseDefaultAddress = TRUE; + if (efi_net_def_addr) { + udata.UseDefaultAddress = TRUE; + } else { + udata.UseDefaultAddress = FALSE; + memcpy(&udata.StationAddress, &IPInfo.myip, sizeof(IPInfo.myip)); + memcpy(&udata.StationAddress, &IPInfo.netmask, sizeof(IPInfo.netmask)); + } memcpy(&udata.RemoteAddress, &ip, sizeof(ip)); udata.RemotePort = port; udata.TimeToLive = 64; @@ -243,6 +255,10 @@ int core_udp_recv(struct pxe_pvt_inode *socket, void *buf, uint16_t *buf_len, uefi_call_wrapper(udp->Cancel, 2, udp, &token); dprintf("core_udp_recv: timed out\n"); + if (!efi_udp_has_recv && (efi_net_def_addr == 1)) { + efi_net_def_addr = 0; + Print(L"disable UseDefaultAddress\n"); + } } uefi_call_wrapper(udp->Poll, 1, udp); @@ -257,6 +273,9 @@ int core_udp_recv(struct pxe_pvt_inode *socket, void *buf, uint16_t *buf_len, if (rv) goto bail; + if (!efi_udp_has_recv) + efi_udp_has_recv = 1; + rxdata = token.Packet.RxData; frag = &rxdata->FragmentTable[0]; @@ -373,7 +392,13 @@ void core_udp_sendto(struct pxe_pvt_inode *socket, const void *data, /* Re-use the existing local port number */ udata.StationPort = socket->net.efi.localport; - udata.UseDefaultAddress = TRUE; + if (efi_net_def_addr) { + udata.UseDefaultAddress = TRUE; + } else { + udata.UseDefaultAddress = FALSE; + memcpy(&udata.StationAddress, &IPInfo.myip, sizeof(IPInfo.myip)); + memcpy(&udata.StationAddress, &IPInfo.netmask, sizeof(IPInfo.netmask)); + } memcpy(&udata.RemoteAddress, &ip, sizeof(ip)); udata.RemotePort = port; udata.TimeToLive = 64; diff --git a/extlinux/Makefile b/extlinux/Makefile index 02d1db51..1721ee54 100644 --- a/extlinux/Makefile +++ b/extlinux/Makefile @@ -27,6 +27,7 @@ SRCS = main.c \ ../libinstaller/syslxmod.c \ ../libinstaller/syslxopt.c \ ../libinstaller/syslxcom.c \ + ../libinstaller/syslxrw.c \ ../libinstaller/setadv.c \ ../libinstaller/advio.c \ ../libinstaller/bootsect_bin.c \ diff --git a/extlinux/main.c b/extlinux/main.c index 6ba16e1e..a7ebd49a 100644 --- a/extlinux/main.c +++ b/extlinux/main.c @@ -14,7 +14,7 @@ /* * extlinux.c * - * Install the syslinux boot block on an fat, ntfs, ext2/3/4, btrfs, xfs, + * Install the syslinux boot block on a fat, ntfs, ext2/3/4, btrfs, xfs, * and ufs1/2 filesystem. */ @@ -56,6 +56,7 @@ #include "version.h" #include "syslxint.h" #include "syslxcom.h" /* common functions shared with extlinux and syslinux */ +#include "syslxrw.h" #include "syslxfs.h" #include "setadv.h" #include "syslxopt.h" /* unified options */ @@ -337,6 +338,59 @@ static int patch_file_and_bootblock(int fd, const char *dir, int devfd) return rv; } +static int ext_read_adv_offset(int devfd, off_t offset) +{ + const size_t adv_size = 2 * ADV_SIZE; + + if (xpread(devfd, syslinux_adv, adv_size, offset) != adv_size) + return -1; + + return syslinux_validate_adv(syslinux_adv) ? 1 : 0; +} + +static int ext_read_adv(const char *path, int devfd, const char **namep) +{ + int err; + const char *name; + + if (fs_type == BTRFS) { + /* btrfs "ldlinux.sys" is in 64k blank area */ + return ext_read_adv_offset(devfd, BTRFS_ADV_OFFSET); + } else if (fs_type == XFS) { + /* XFS "ldlinux.sys" is in the first 2048 bytes of the primary AG */ + return ext_read_adv_offset(devfd, boot_image_len); + } else { + err = read_adv(path, name = "ldlinux.sys"); + if (err == 2) /* ldlinux.sys does not exist */ + err = read_adv(path, name = "extlinux.sys"); + if (namep) + *namep = name; + return err; + } +} + +static int ext_write_adv_offset(int devfd, off_t offset) +{ + const size_t adv_size = 2 * ADV_SIZE; + + if (xpwrite(devfd, syslinux_adv, adv_size, offset) != adv_size) { + perror("writing adv"); + return 1; + } + + return 0; +} + +static int ext_write_adv(const char *path, const char *cfg, int devfd) +{ + if (fs_type == BTRFS) { + /* btrfs "ldlinux.sys" is in 64k blank area */ + return ext_write_adv_offset(devfd, BTRFS_ADV_OFFSET); + } else { + return write_adv(path, cfg); + } +} + /* * Install the boot block on the specified device. * Must be run AFTER install_file()! @@ -392,11 +446,11 @@ int install_bootblock(int fd, const char *device) if (sb5.sb_magicnum == *(u32 *)XFS_SB_MAGIC) { if (be32_to_cpu(sb5.sb_blocksize) != XFS_SUPPORTED_BLOCKSIZE) { fprintf(stderr, - "You need to have 4 KiB filesystem block size for " - " being able to install Syslinux in your XFS " - "partition (because there is no enough space in MBR to " - "determine where Syslinux bootsector can be installed " - "regardless the filesystem block size)\n"); + "You need to have 4 KiB filesystem block size for" + " being able to install Syslinux in your XFS" + " partition (because there is not enough space in MBR to" + " determine where Syslinux bootsector can be installed" + " regardless of the filesystem block size)\n"); return 1; } @@ -419,8 +473,8 @@ int install_bootblock(int fd, const char *device) if (!ok) { fprintf(stderr, - "no fat, ntfs, ext2/3/4, btrfs, xfs " - "or ufs1/2 superblock found on %s\n", + "no fat, ntfs, ext2/3/4, btrfs, xfs" + " or ufs1/2 superblock found on %s\n", device); return 1; } @@ -483,8 +537,7 @@ static int rewrite_boot_image(int devfd, const char *path, const char *filename) } /* Write ADV */ - ret = xpwrite(fd, syslinux_adv, 2 * ADV_SIZE, boot_image_len); - if (ret != 2 * ADV_SIZE) { + if (ext_write_adv_offset(fd, boot_image_len)) { fprintf(stderr, "%s: write failure on %s\n", program, filename); goto error; } @@ -597,9 +650,12 @@ bail: return 1; } -/* btrfs has to install the ldlinux.sys in the first 64K blank area, which - is not managered by btrfs tree, so actually this is not installed as files. - since the cow feature of btrfs will move the ldlinux.sys every where */ +/* btrfs has to install ldlinux.sys to a boot area, which is not managed by + btrfs tree, so actually this is not installed as a file, since the cow + feature of btrfs would move the ldlinux.sys file everywhere. Older + versions installed it to the first 64kiB (aka Boot Area A) but as of + commit ID 37eef640 (before 6.03-pre12, before 6.03), it is now in Boot + Area B (a 768kiB blank space at offset 256kiB). */ int btrfs_install_file(const char *path, int devfd, struct stat *rst) { char *file; @@ -613,9 +669,7 @@ int btrfs_install_file(const char *path, int devfd, struct stat *rst) return 1; } dprintf("write boot_image to 0x%x\n", BTRFS_EXTLINUX_OFFSET); - if (xpwrite(devfd, syslinux_adv, 2 * ADV_SIZE, BTRFS_ADV_OFFSET) - != 2 * ADV_SIZE) { - perror("writing adv"); + if (ext_write_adv_offset(devfd, BTRFS_ADV_OFFSET)) { return 1; } dprintf("write adv to 0x%x\n", BTRFS_ADV_OFFSET); @@ -661,7 +715,7 @@ int btrfs_install_file(const char *path, int devfd, struct stat *rst) * Due to historical reasons (SGI IRIX's design of disk layouts), the first * sector in the primary AG on XFS filesystems contains the superblock, which is * a problem with bootloaders that rely on BIOSes (that load VBRs which are - * (located in the first sector of the partition). + * located in the first sector of the partition). * * Thus, we need to handle this issue, otherwise Syslinux will damage the XFS's * superblock. @@ -750,7 +804,7 @@ bail: * * test if path is a subvolume: * * this function return * * 0-> path exists but it is not a subvolume - * * 1-> path exists and it is a subvolume + * * 1-> path exists and it is a subvolume * * -1 -> path is unaccessible * */ static int test_issubvolume(char *path) @@ -1384,8 +1438,8 @@ static int open_device(const char *path, struct stat *st, char **_devname) if (!fs_type) { fprintf(stderr, - "%s: not a fat, ntfs, ext2/3/4, btrfs, xfs or" - "ufs1/2 filesystem: %s\n", + "%s: not a fat, ntfs, ext2/3/4, btrfs, xfs" + " or ufs1/2 filesystem: %s\n", program, path); return -1; } @@ -1414,59 +1468,6 @@ static int open_device(const char *path, struct stat *st, char **_devname) return devfd; } -static int btrfs_read_adv(int devfd) -{ - if (xpread(devfd, syslinux_adv, 2 * ADV_SIZE, BTRFS_ADV_OFFSET) - != 2 * ADV_SIZE) - return -1; - - return syslinux_validate_adv(syslinux_adv) ? 1 : 0; -} - -static inline int xfs_read_adv(int devfd) -{ - const size_t adv_size = 2 * ADV_SIZE; - - if (xpread(devfd, syslinux_adv, adv_size, boot_image_len) != adv_size) - return -1; - - return syslinux_validate_adv(syslinux_adv) ? 1 : 0; -} - -static int ext_read_adv(const char *path, int devfd, const char **namep) -{ - int err; - const char *name; - - if (fs_type == BTRFS) { - /* btrfs "ldlinux.sys" is in 64k blank area */ - return btrfs_read_adv(devfd); - } else if (fs_type == XFS) { - /* XFS "ldlinux.sys" is in the first 2048 bytes of the primary AG */ - return xfs_read_adv(devfd); - } else { - err = read_adv(path, name = "ldlinux.sys"); - if (err == 2) /* ldlinux.sys does not exist */ - err = read_adv(path, name = "extlinux.sys"); - if (namep) - *namep = name; - return err; - } -} - -static int ext_write_adv(const char *path, const char *cfg, int devfd) -{ - if (fs_type == BTRFS) { /* btrfs "ldlinux.sys" is in 64k blank area */ - if (xpwrite(devfd, syslinux_adv, 2 * ADV_SIZE, - BTRFS_ADV_OFFSET) != 2 * ADV_SIZE) { - perror("writing adv"); - return 1; - } - return 0; - } - return write_adv(path, cfg); -} - static int install_loader(const char *path, int update_only) { struct stat st, fst; diff --git a/libinstaller/advio.c b/libinstaller/advio.c index 66e477ed..e282e11c 100644 --- a/libinstaller/advio.c +++ b/libinstaller/advio.c @@ -32,6 +32,7 @@ #include <sys/stat.h> #include <sys/types.h> #include "syslxint.h" +#include "syslxrw.h" #include "syslxcom.h" /* diff --git a/libinstaller/syslxcom.c b/libinstaller/syslxcom.c index 57f13cda..efc6474d 100644 --- a/libinstaller/syslxcom.c +++ b/libinstaller/syslxcom.c @@ -32,6 +32,7 @@ #include <sys/vfs.h> #include "linuxioctl.h" +#include "syslxrw.h" #include "syslxcom.h" #include "syslxfs.h" @@ -47,69 +48,6 @@ int fs_type; #define SECTOR_SHIFT 9 -static void die(const char *msg) -{ - fputs(msg, stderr); - exit(1); -} - -/* - * read/write wrapper functions - */ -ssize_t xpread(int fd, void *buf, size_t count, off_t offset) -{ - char *bufp = (char *)buf; - ssize_t rv; - ssize_t done = 0; - - while (count) { - rv = pread(fd, bufp, count, offset); - if (rv == 0) { - die("short read"); - } else if (rv == -1) { - if (errno == EINTR) { - continue; - } else { - die(strerror(errno)); - } - } else { - bufp += rv; - offset += rv; - done += rv; - count -= rv; - } - } - - return done; -} - -ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset) -{ - const char *bufp = (const char *)buf; - ssize_t rv; - ssize_t done = 0; - - while (count) { - rv = pwrite(fd, bufp, count, offset); - if (rv == 0) { - die("short write"); - } else if (rv == -1) { - if (errno == EINTR) { - continue; - } else { - die(strerror(errno)); - } - } else { - bufp += rv; - offset += rv; - done += rv; - count -= rv; - } - } - - return done; -} - /* * Set and clear file attributes */ diff --git a/libinstaller/syslxcom.h b/libinstaller/syslxcom.h index 8b3b4614..90d3966c 100644 --- a/libinstaller/syslxcom.h +++ b/libinstaller/syslxcom.h @@ -4,8 +4,6 @@ #include "syslinux.h" extern const char *program; -ssize_t xpread(int fd, void *buf, size_t count, off_t offset); -ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset); void clear_attributes(int fd); void set_attributes(int fd); int sectmap(int fd, sector_t *sectors, int nsectors); diff --git a/libinstaller/syslxrw.c b/libinstaller/syslxrw.c new file mode 100644 index 00000000..86876e8c --- /dev/null +++ b/libinstaller/syslxrw.c @@ -0,0 +1,84 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010 Intel Corp. - All Rights Reserved + * Copyright 2015 Paulo Alcantara <pcacjr@zytor.com> + * + * 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, Inc., 53 Temple Place Ste 330, + * Boston MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> + +#include "syslxrw.h" + +static void die(const char *msg) +{ + fputs(msg, stderr); + exit(1); +} + +/* + * read/write wrapper functions + */ +ssize_t xpread(int fd, void *buf, size_t count, off_t offset) +{ + char *bufp = (char *)buf; + ssize_t rv; + ssize_t done = 0; + + while (count) { + rv = pread(fd, bufp, count, offset); + if (rv == 0) { + die("short read"); + } else if (rv == -1) { + if (errno == EINTR) { + continue; + } else { + die(strerror(errno)); + } + } else { + bufp += rv; + offset += rv; + done += rv; + count -= rv; + } + } + + return done; +} + +ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset) +{ + const char *bufp = (const char *)buf; + ssize_t rv; + ssize_t done = 0; + + while (count) { + rv = pwrite(fd, bufp, count, offset); + if (rv == 0) { + die("short write"); + } else if (rv == -1) { + if (errno == EINTR) { + continue; + } else { + die(strerror(errno)); + } + } else { + bufp += rv; + offset += rv; + done += rv; + count -= rv; + } + } + + return done; +} diff --git a/libinstaller/syslxrw.h b/libinstaller/syslxrw.h new file mode 100644 index 00000000..d3ae3c29 --- /dev/null +++ b/libinstaller/syslxrw.h @@ -0,0 +1,20 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010 Intel Corp. - All Rights Reserved + * Copyright 2015 Paulo Alcantara <pcacjr@zytor.com> + * + * 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, Inc., 53 Temple Place Ste 330, + * Boston MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#ifndef _H_SYSLXRW_ +#define _H_SYSLXRW_ + +ssize_t xpread(int fd, void *buf, size_t count, off_t offset); +ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset); + +#endif /* _H_SYSLXRW_ */ diff --git a/linux/Makefile b/linux/Makefile index 11667e1d..5a49d813 100644 --- a/linux/Makefile +++ b/linux/Makefile @@ -23,6 +23,7 @@ LDFLAGS = SRCS = syslinux.c \ ../libinstaller/syslxopt.c \ + ../libinstaller/syslxrw.c \ ../libinstaller/syslxcom.c \ ../libinstaller/setadv.c \ ../libinstaller/advio.c \ diff --git a/linux/syslinux.c b/linux/syslinux.c index 912de71f..46d5624c 100755 --- a/linux/syslinux.c +++ b/linux/syslinux.c @@ -68,6 +68,7 @@ #include <getopt.h> #include <sysexits.h> +#include "syslxrw.h" #include "syslxcom.h" #include "syslxfs.h" #include "setadv.h" diff --git a/mk/com32.mk b/mk/com32.mk index 90eb7edd..2e8591a7 100644 --- a/mk/com32.mk +++ b/mk/com32.mk @@ -48,7 +48,9 @@ GCCOPT += $(call gcc_ok,-falign-jumps=0,-malign-jumps=0) GCCOPT += $(call gcc_ok,-falign-labels=0,-malign-labels=0) GCCOPT += $(call gcc_ok,-falign-loops=0,-malign-loops=0) -ifndef EFI_BUILD +ifdef EFI_BUILD +GCCOPT += -mno-red-zone +else GCCOPT += -mregparm=3 -DREGPARM=3 endif @@ -60,8 +60,10 @@ CFLAGS = $(GCCOPT) $(GCCWARN) -W -Wall \ -I$(com32)/libutil/include -I$(com32)/include \ -I$(com32)/include/sys $(GPLINCLUDE) -I$(core)/include \ -I$(objdir) -DLDLINUX=\"$(LDLINUX)\" -ifndef EFI_BUILD -CFLAGS += -mregparm=3 -DREGPARM=3 +ifdef EFI_BUILD +GCCOPT += -mno-red-zone +else +GCCOPT += -mregparm=3 -DREGPARM=3 endif SFLAGS = $(GCCOPT) -D__COM32__ -D__FIRMWARE_$(FIRMWARE)__ diff --git a/mk/embedded.mk b/mk/embedded.mk index 1614d8bc..df8e85f3 100644 --- a/mk/embedded.mk +++ b/mk/embedded.mk @@ -39,10 +39,9 @@ GCCOPT += $(call gcc_ok,-fno-stack-protector,) GCCOPT += $(call gcc_ok,-fwrapv,) GCCOPT += $(call gcc_ok,-freg-struct-return,) ifdef EFI_BUILD -GCCOPT += -Os -fomit-frame-pointer -msoft-float +GCCOPT += -Os -fomit-frame-pointer -msoft-float -mno-red-zone else -GCCOPT += -Os -fomit-frame-pointer -mregparm=3 -DREGPARM=3 \ - -msoft-float +GCCOPT += -Os -fomit-frame-pointer -mregparm=3 -DREGPARM=3 -msoft-float endif GCCOPT += $(call gcc_ok,-fno-exceptions,) GCCOPT += $(call gcc_ok,-fno-asynchronous-unwind-tables,) @@ -54,7 +54,9 @@ WARNFLAGS = $(GCCWARN) -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Winl CFLAGS = $(OPTFLAGS) $(REQFLAGS) $(WARNFLAGS) $(LIBFLAGS) -ifndef EFI_BUILD +ifdef EFI_BUILD +CFLAGS += -mno-red-zone +else CFLAGS += -mregparm=3 -DREGPARM=3 endif diff --git a/mk/syslinux.mk b/mk/syslinux.mk index 337560bb..46355c9e 100644 --- a/mk/syslinux.mk +++ b/mk/syslinux.mk @@ -82,11 +82,11 @@ ARCH ?= $(strip $(SUBARCH)) GCCWARN = -W -Wall -Wstrict-prototypes $(DEBUGOPT) # Common stanza to make gcc generate .*.d dependency files -MAKEDEPS = -Wp,-MT,$@,-MD,$(dir $@).$(notdir $@).d +MAKEDEPS = -MT $@ -MD -MF $(dir $@).$(notdir $@).d # Dependencies that exclude system headers; use whenever we use # header files from the platform. -UMAKEDEPS = -Wp,-MT,$@,-MMD,$(dir $@).$(notdir $@).d +UMAKEDEPS = -MT $@ -MMD -MF $(dir $@).$(notdir $@).d # Items that are only appropriate during development; this file is # removed when tarballs are generated. diff --git a/mtools/Makefile b/mtools/Makefile index 0d0b1b27..632b185b 100755 --- a/mtools/Makefile +++ b/mtools/Makefile @@ -9,6 +9,7 @@ SRCS = syslinux.c \ ../libinstaller/fs.c \ ../libinstaller/syslxmod.c \ ../libinstaller/syslxopt.c \ + ../libinstaller/syslxrw.c \ ../libinstaller/setadv.c \ ../libinstaller/bootsect_bin.c \ ../libinstaller/ldlinux_bin.c \ diff --git a/mtools/syslinux.c b/mtools/syslinux.c index 59244307..9d68882f 100755 --- a/mtools/syslinux.c +++ b/mtools/syslinux.c @@ -42,8 +42,9 @@ #include "setadv.h" #include "syslxopt.h" #include "syslxfs.h" +#include "syslxrw.h" -char *program; /* Name of program */ +const char *program; pid_t mypid; void __attribute__ ((noreturn)) die(const char *msg) @@ -59,63 +60,6 @@ void __attribute__ ((noreturn)) die_err(const char *msg) } /* - * read/write wrapper functions - */ -ssize_t xpread(int fd, void *buf, size_t count, off_t offset) -{ - char *bufp = (char *)buf; - ssize_t rv; - ssize_t done = 0; - - while (count) { - rv = pread(fd, bufp, count, offset); - if (rv == 0) { - die("short read"); - } else if (rv == -1) { - if (errno == EINTR) { - continue; - } else { - die(strerror(errno)); - } - } else { - bufp += rv; - offset += rv; - done += rv; - count -= rv; - } - } - - return done; -} - -ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset) -{ - const char *bufp = (const char *)buf; - ssize_t rv; - ssize_t done = 0; - - while (count) { - rv = pwrite(fd, bufp, count, offset); - if (rv == 0) { - die("short write"); - } else if (rv == -1) { - if (errno == EINTR) { - continue; - } else { - die(strerror(errno)); - } - } else { - bufp += rv; - offset += rv; - done += rv; - count -= rv; - } - } - - return done; -} - -/* * Version of the read function suitable for libfat */ int libfat_xpread(intptr_t pp, void *buf, size_t secsize, diff --git a/tests/Makefile b/tests/Makefile index 99b1618f..7c0f9794 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -39,7 +39,7 @@ QEMU = qemu-system-i386 all: syslinux-tests pxelinux-tests syslinux-tests: - $(MAKE) SRC="$(SRC)" OBJ="$(OBJ)" objdir="$(objdir)" \ + $(MAKE) SRC="$(SRC)" OBJ="$(OBJ)" objdir="$(objdir)" EFI_BUILD=$(EFI_BUILD) \ INITIAL="$(INITIAL)" INSTALL_DIR="$(SYSLINUX_INSTALL_DIR)" \ CONFIG_FILE="$(SYSLINUX_CONFIG_FILE)" \ DERIVATIVE=SYSLINUX @@ -47,7 +47,7 @@ syslinux-tests: $(SYSLINUX_LOOPDEV) test.cfg pxelinux-tests: - $(MAKE) SRC="$(SRC)" OBJ="$(OBJ)" objdir="$(objdir)" \ + $(MAKE) SRC="$(SRC)" OBJ="$(OBJ)" objdir="$(objdir)" EFI_BUILD=$(EFI_BUILD) \ INITIAL="$(INITIAL)" INSTALL_DIR="$(PXELINUX_INSTALL_DIR)" \ CONFIG_FILE="$(PXELINUX_CONFIG_FILE)" \ DERIVATIVE=PXELINUX @@ -71,7 +71,7 @@ SUBDIRS = linux com32 subdirs: $(SUBDIRS) $(SUBDIRS): mkdir -p $(OBJ)/$@ - $(MAKE) -C $(OBJ)/$@ SRC="$(SRC)"/$@ OBJ="$(OBJ)"/$@/ \ + $(MAKE) -C $(OBJ)/$@ SRC="$(SRC)"/$@ OBJ="$(OBJ)"/$@/ EFI_BUILD=$(EFI_BUILD) \ -f $(SRC)/$@/Makefile objdir="$(objdir)/tests" \ INSTALL_DIR="$(INSTALL_DIR)" CONFIG_FILE="$(CONFIG_FILE)" \ DERIVATIVE="$(DERIVATIVE)" |