Robert Yang
2014-Dec-24 08:16 UTC
[syslinux] [PATCH 0/8] extlinux: support unmounted ext2/3/4 filesystem
Hello syslinux, Merry Christmas! These patches will make extlinux work with umounted ext2/3/4 filesystem, for example: $ extlinux -i /dev/sdXN or $ extlinux -i file_block Also it can work with something like: $ extlinux /dev/sdXN --reset-adv or $ extlinux file_block --reset-adv We don't use a new option (I planed to use "-d" but it is already in use), it will check whether the target is a directory or device and decide what to do, it would stop and error if the device is mounted. I put these patches on github so that you can easily get them in case you'd like to test them. (The repo's name is sys_tmp, which avoids confusing others, I will remove the repo when these patches are reviewed). More info: * It will use libext2fs to read and write the file. * It will be used when the target is a extX device or file block, and work as before when the target is a directory. * It will be used for both modifing the existing adv when update_only == -1, and install the files to the filesystem. We will begin to use this feature in Yocto Project once it is fine to the syslinux community. Please feel free to give your comments. // Robert The following changes since commit 81ad566f155fac31089fde69c87059b217e7e9b6: NEWS: Update for 6.03 release (2014-10-06 09:27:44 -0700) are available in the git repository at: https://github.com/robertlinux/sys_tmp.git unmounted_ext for you to fetch changes up to a3603826b88c5f000c5b0ba519cd0a5252eb6c6b: libinstaller/syslxopt.c: update the help text. (2014-12-24 16:07:50 +0800) Robert Yang (8): extlinux/main.c: support unmounted ext2/3/4 filesystem extlinux/main.c: implement install_file_to_device() extlinux/main.c: implement handle_adv_on_device() extlinux/main.c: implent ext_read/write_xx_fs() extlinux/main.c: implement write_to_device() extlinux/main.c: implement patch_syslinux_bootsect() extlinux/main.c: implement ext_construct_sectmap_fs() libinstaller/syslxopt.c: update the help text. extlinux/Makefile | 2 +- extlinux/main.c | 611 +++++++++++++++++++++++++++++++++++++++++++----- libinstaller/syslxopt.c | 2 +- 3 files changed, 553 insertions(+), 62 deletions(-) -- 1.9.1
Robert Yang
2014-Dec-24 08:16 UTC
[syslinux] [PATCH 1/8] extlinux/main.c: support unmounted ext2/3/4 filesystem
Add install_file_to_device() to support unmounted ext2, ext3 and ext4 filesystem. Usage: $ extlinux -i /dev/sdXN or $ extlinux -i file_block We don't need any new options, it will check whether the target is a directory or device and decide what to do, it would stop and error if the device is mounted. More info: * It will use libext2fs to read and write the file. * It will be used when the target is a extX device or file block, and work as before when the target is a directory. * It will be used for both modifing the existing adv when update_only == -1, and install the files to the filesystem. Signed-off-by: Robert Yang <liezhi.yang at windriver.com> --- extlinux/Makefile | 2 +- extlinux/main.c | 96 ++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 67 insertions(+), 31 deletions(-) diff --git a/extlinux/Makefile b/extlinux/Makefile index 02d1db5..f7035c7 100644 --- a/extlinux/Makefile +++ b/extlinux/Makefile @@ -52,7 +52,7 @@ spotless: clean installer: extlinux extlinux: $(OBJS) - $(CC) $(LDFLAGS) -o $@ $^ + $(CC) $(LDFLAGS) -o $@ $^ -lext2fs strip: $(STRIP) extlinux diff --git a/extlinux/main.c b/extlinux/main.c index 09740bd..9132ce5 100644 --- a/extlinux/main.c +++ b/extlinux/main.c @@ -41,6 +41,7 @@ #include <sys/types.h> #include <sys/mount.h> #include <sys/vfs.h> +#include <ext2fs/ext2fs.h> #include "linuxioctl.h" @@ -991,6 +992,12 @@ static int install_file(const char *path, int devfd, struct stat *rst) return 1; } + +static int install_file_to_device(const char *device_path, int devfd, + int update_only) +{ +} + #ifdef __KLIBC__ static char devname_buf[64]; @@ -1452,15 +1459,26 @@ static int ext_write_adv(const char *path, const char *cfg, int devfd) return write_adv(path, cfg); } -static int install_loader(const char *path, int update_only) +static int install_loader(const char *path, int update_only, struct stat st) { - struct stat st, fst; + struct stat fst; int devfd, rv; const char *devname; - devfd = open_device(path, &st, &devname); - if (devfd < 0) - return 1; + /* Support dir, ext2, ext3 and ext4 filesystem (device or file block) */ + if S_ISDIR(st.st_mode) { + devfd = open_device(path, &st, &devname); + if (devfd < 0) + return 1; + } else if (S_ISBLK(st.st_mode) || S_ISREG(st.st_mode)) { + if ((devfd = open(path, O_RDWR | O_SYNC)) < 0) { + fprintf(stderr, "%s: cannot open device %s\n", program, devname); + return -1; + } + } else { + fprintf(stderr, "%s: unsupported file type: %s\n", program, path); + return -1; + } if (update_only && !syslinux_already_installed(devfd)) { fprintf(stderr, "%s: no previous syslinux boot sector found\n", @@ -1469,29 +1487,38 @@ static int install_loader(const char *path, int update_only) return 1; } - /* Read a pre-existing ADV, if already installed */ - if (opt.reset_adv) { - syslinux_reset_adv(syslinux_adv); - } else if (ext_read_adv(path, devfd, NULL) < 0) { - close(devfd); - return 1; - } + if S_ISDIR(st.st_mode) { + /* Read a pre-existing ADV, if already installed */ + if (opt.reset_adv) { + syslinux_reset_adv(syslinux_adv); + } else if (ext_read_adv(path, devfd, NULL) < 0) { + close(devfd); + return 1; + } - if (modify_adv() < 0) { - close(devfd); - return 1; - } + if (modify_adv() < 0) { + close(devfd); + return 1; + } - /* Install ldlinux.sys */ - if (install_file(path, devfd, &fst)) { - close(devfd); - return 1; - } - if (fst.st_dev != st.st_dev) { - fprintf(stderr, "%s: file system changed under us - aborting!\n", - program); - close(devfd); - return 1; + /* Install ldlinux.sys */ + if (install_file(path, devfd, &fst)) { + close(devfd); + return 1; + } + if (fst.st_dev != st.st_dev) { + fprintf(stderr, "%s: file system changed under us - aborting!\n", + program); + close(devfd); + return 1; + } + } else { + if (install_file_to_device(path, devfd, update_only)) { + fprintf(stderr, "%s: install file to device error!\n", program); + close(devfd); + return 1; + } + fs_type = EXT2; } sync(); @@ -1533,16 +1560,25 @@ int modify_existing_adv(const char *path) int main(int argc, char *argv[]) { parse_options(argc, argv, MODE_EXTLINUX); + struct stat st; if (!opt.directory || opt.install_mbr || opt.activate_partition) usage(EX_USAGE, 0); + if (stat(opt.directory, &st)) { + fprintf(stderr, "%s: %s: %s\n", program, opt.directory, strerror(errno)); + return 1; + } + if (opt.update_only == -1) { - if (opt.reset_adv || opt.set_once || opt.menu_save) - return modify_existing_adv(opt.directory); - else + if (opt.reset_adv || opt.set_once || opt.menu_save) { + if S_ISDIR(st.st_mode) + return modify_existing_adv(opt.directory); + else if (S_ISBLK(st.st_mode) || S_ISREG(st.st_mode)) + return install_file_to_device(opt.directory, -1, opt.update_only); + } else usage(EX_USAGE, MODE_EXTLINUX); } - return install_loader(opt.directory, opt.update_only); + return install_loader(opt.directory, opt.update_only, st); } -- 1.9.1
Robert Yang
2014-Dec-24 08:16 UTC
[syslinux] [PATCH 2/8] extlinux/main.c: implement install_file_to_device()
* Check wether the filesystem is mounted or not, stop going if mounted. * Use ext2fs_open() to open the fs, preparing for reading and writing. * The handle_adv_on_device() will read, reset and write the adv (when update_only == -1). * Write the file to device. * Remove the old file extlinux.sys if found. Signed-off-by: Robert Yang <liezhi.yang at windriver.com> --- extlinux/main.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/extlinux/main.c b/extlinux/main.c index 9132ce5..23c1851 100644 --- a/extlinux/main.c +++ b/extlinux/main.c @@ -993,9 +993,122 @@ static int install_file(const char *path, int devfd, struct stat *rst) } +static int write_to_device(ext2_filsys fs, const char *filename, + const char *str, int length, int i_flags, + int devfd) +{ +} + +static int handle_adv_on_device(ext2_filsys fs, int update_only) +{ +} + static int install_file_to_device(const char *device_path, int devfd, int update_only) { + int retval; + ext2_filsys fs = NULL; + int open_flag = EXT2_FLAG_RW, mount_flags; + ext2_ino_t oldino; + ext2_ino_t root = EXT2_ROOT_INO; + + const char *file = "ldlinux.sys"; + const char *oldfile = "extlinux.sys"; + const char *c32file = "ldlinux.c32"; + + + retval = ext2fs_check_if_mounted(device_path, &mount_flags); + if (retval) { + fprintf(stderr, "%s: ext2fs_check_if_mount() error on %s\n", + program, device_path); + return -1; + } + + if (mount_flags & EXT2_MF_MOUNTED) { + fprintf(stderr, "%s: ERROR: %s is mounted, you need use the mount\n\ + point as the install dir or umount it to use the device as\n\ + the install device\n", + program, device_path); + return -1; + } + + /* Open the fs */ + retval = ext2fs_open(device_path, open_flag, 0, 0, unix_io_manager, &fs); + if (retval) { + fprintf(stderr, "%s: ERROR: while trying to open: %s\n", + program, device_path); + if (retval == EXT2_ET_BAD_MAGIC) + fprintf(stderr, + "%s: ERROR: only ext2, ext3 and ext4 is supported for umounted fs\n", + program); + return -1; + } + + fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE; + + /* Read the inode map */ + retval = ext2fs_read_inode_bitmap(fs); + if (retval) { + fprintf(stderr, "%s: ERROR: while reading inode bitmap: %s\n", + program, device_path); + goto fail; + } + + /* Read the block map */ + retval = ext2fs_read_block_bitmap(fs); + if (retval) { + fprintf(stderr, "%s: ERROR: while reading block bitmap: %s\n", + program, device_path); + goto fail; + } + + if (handle_adv_on_device(fs, update_only) < 0) { + fprintf(stderr, "%s: ERROR: while handling ADV on %s\n", + program, device_path); + retval = 1; + goto fail; + } + + /* Return from here if only need update the adv */ + if (update_only == -1) { + return ext2fs_close(fs); + } + + /* Write ldlinux.sys */ + retval = write_to_device(fs, file, (const char _force *)boot_image, + boot_image_len, EXT2_IMMUTABLE_FL, devfd); + if (retval) { + fprintf(stderr, "%s: ERROR: while writing: %s.\n", + program, file); + goto fail; + } + + /* Write ldlinux.c32 */ + retval = write_to_device(fs, c32file, + (const char _force *)syslinux_ldlinuxc32, + syslinux_ldlinuxc32_len, 0, devfd); + if (retval) { + fprintf(stderr, "%s: ERROR: while writing: %s.\n", + program, c32file); + goto fail; + } + + /* Look if we have the extlinux.sys and remove it*/ + retval = ext2fs_namei(fs, root, root, oldfile, &oldino); + if (retval == 0) { + dprintf("%s: found %s, removing it\n", program, oldfile); + retval = ext2fs_unlink(fs, root, oldfile, oldino, 0); + if (retval) { + fprintf(stderr, "%s: ERROR: failed to unlink: %s\n", program, oldfile); + goto fail; + } + } else { + retval = 0; + } + +fail: + (void) ext2fs_close(fs); + return retval; } #ifdef __KLIBC__ -- 1.9.1
Robert Yang
2014-Dec-24 08:16 UTC
[syslinux] [PATCH 3/8] extlinux/main.c: implement handle_adv_on_device()
It reads, reset or write the adv (when update_only = -1) on the fs. Signed-off-by: Robert Yang <liezhi.yang at windriver.com> --- extlinux/main.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/extlinux/main.c b/extlinux/main.c index 23c1851..4205f09 100644 --- a/extlinux/main.c +++ b/extlinux/main.c @@ -992,6 +992,18 @@ static int install_file(const char *path, int devfd, struct stat *rst) return 1; } +/* Read from an ext2_file */ +static int ext_read_from_fs(ext2_file_t e2_file, void *buf, size_t count, + off_t offset, const char *msg) +{ +} + +/* Write to an ext2_file */ +static int ext_write_to_fs(ext2_file_t e2_file, const void *buf, size_t count, + off_t offset, const char *msg) +{ +} + static int write_to_device(ext2_filsys fs, const char *filename, const char *str, int length, int i_flags, @@ -1001,6 +1013,106 @@ static int write_to_device(ext2_filsys fs, const char *filename, static int handle_adv_on_device(ext2_filsys fs, int update_only) { + ext2_ino_t root = EXT2_ROOT_INO; + int i, retval, found_file; + int need_close = 2; /* 2 means no need extra close */ + char *filenames[2] = {"ldlinux.sys", "extlinux.sys"}; + char *filename; + ext2_ino_t newino; + ext2_file_t e2_file; + struct ext2_inode inode; + + for (i = 0; i < 2; i++) { + filename = filenames[i]; + found_file = 0; + retval = ext2fs_namei(fs, root, root, filename, &newino); + if (retval == 0) { + dprintf("%s: found file %s, reading ADV from it\n", + program, filename); + found_file = 1; + } else + continue; + + need_close = i; + + retval = ext2fs_file_open(fs, newino, EXT2_FLAG_RW, &e2_file); + if (retval) { + fprintf(stderr, "%s: ERROR: failed to open %s\n", + program, filename); + goto fail; + } + + retval = ext2fs_read_inode(fs, newino, &inode); + if (retval) { + fprintf(stderr, "%s: ERROR: while reading inode: %u, file: %s\n", + program, newino, filename); + goto fail; + } + + /* Check the size to see if too small to read */ + if (inode.i_size < 2 * ADV_SIZE) { + if (update_only == -1) { + fprintf(stderr, "%s: ERROR: failed to write auxilliary data\n\ + the size of %s is too small (need --update)?\n", + program, filename); + retval = -1; + goto fail; + } + syslinux_reset_adv(syslinux_adv); + found_file = 0; + break; + } + + /* Read the adv */ + retval = ext_read_from_fs(e2_file, syslinux_adv, 2 * ADV_SIZE, + inode.i_size - 2 * ADV_SIZE, "ADV"); + if (retval == -1) + goto fail; + if (retval == 2 * ADV_SIZE) { + retval = syslinux_validate_adv(syslinux_adv); + /* Read the adv successfully */ + if (retval == 0) + break; + } + + /* Close the file if reaches here, otherwise we leave the file + * open in case we need write it */ + need_close = 2; + retval = ext2fs_file_close(e2_file); + if (retval) { + fprintf(stderr, "%s: ERROR: while closing %s\n", + program, filename); + return retval; + } + } + + if (!found_file) { + if (update_only == -1) { + fprintf(stderr, "%s: ERROR: no ldlinux.sys or extlinux.sys found on the device\n", + program); + return -1; + } + syslinux_reset_adv(syslinux_adv); + } + + /* The modify_adv will reset the adv if opt.reset_adv */ + if (modify_adv() < 0) { + fprintf(stderr, "%s: ERROR: while modifying adv\n", program); + retval = -1; + goto fail; + } + + /* Write adv if update_only == -1 and found file */ + if (update_only == -1 && found_file) { + if (ext_write_to_fs(e2_file, syslinux_adv, 2 * ADV_SIZE , + inode.i_size - 2 * ADV_SIZE, "ADV") == -1) + goto fail; + } + +fail: + if (need_close != 2) + (void) ext2fs_file_close(e2_file); + return retval; } static int install_file_to_device(const char *device_path, int devfd, -- 1.9.1
Robert Yang
2014-Dec-24 08:16 UTC
[syslinux] [PATCH 4/8] extlinux/main.c: implent ext_read/write_xx_fs()
It uses ext2fs_file_read/write() to reads or write on the ext2_file_t. Signed-off-by: Robert Yang <liezhi.yang at windriver.com> --- extlinux/main.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/extlinux/main.c b/extlinux/main.c index 4205f09..3acf5b5 100644 --- a/extlinux/main.c +++ b/extlinux/main.c @@ -996,14 +996,65 @@ static int install_file(const char *path, int devfd, struct stat *rst) static int ext_read_from_fs(ext2_file_t e2_file, void *buf, size_t count, off_t offset, const char *msg) { + int retval; + char *ptr = (char *) buf; + unsigned int got = 0; + size_t done = 0; + + /* Always lseek since e2_file is uncontrolled by this func */ + if (ext2fs_file_lseek(e2_file, offset, EXT2_SEEK_SET, NULL)) { + fprintf(stderr, "%s: ERROR: ext2fs_file_lseek() failed.\n", + program); + return -1; + } + + dprintf("%s: Reading %s\n", program, msg); + while (1) { + retval = ext2fs_file_read(e2_file, ptr, count, &got); + if (retval) { + fprintf(stderr, "%s: ERROR: while reading %s\n", + program, msg); + return -1; + } + count -= got; + ptr += got; + done += got; + if (got == 0 || count == 0) + break; + } + + return done; } /* Write to an ext2_file */ static int ext_write_to_fs(ext2_file_t e2_file, const void *buf, size_t count, off_t offset, const char *msg) { -} + const char *ptr = (const char *) buf; + unsigned int written = 0; + size_t done = 0; + /* Always lseek since e2_file is uncontrolled by this func */ + if (ext2fs_file_lseek(e2_file, offset, EXT2_SEEK_SET, NULL)) { + fprintf(stderr, "%s: ERROR: ext2fs_file_lseek() failed.\n", + program); + return -1; + } + + dprintf("%s: writing %s\n", program, msg); + while (count > 0) { + if (ext2fs_file_write(e2_file, ptr, count, &written)) { + fprintf(stderr, "%s: ERROR: failed to write syslinux adv.\n", + program); + return -1; + } + count -= written; + ptr += written; + done += written; + } + + return done; +} static int write_to_device(ext2_filsys fs, const char *filename, const char *str, int length, int i_flags, -- 1.9.1
Robert Yang
2014-Dec-24 08:16 UTC
[syslinux] [PATCH 5/8] extlinux/main.c: implement write_to_device()
* Create the file for writting. * Construct the bmap. * Patch the boot sector. * Patch ldlinux.sys. Signed-off-by: Robert Yang <liezhi.yang at windriver.com> --- extlinux/main.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/extlinux/main.c b/extlinux/main.c index 3acf5b5..99a078c 100644 --- a/extlinux/main.c +++ b/extlinux/main.c @@ -222,6 +222,11 @@ ok: return rv; } +/* Patch syslinux_bootsect */ +static void patch_syslinux_bootsect(int devfd) +{ +} + /* * Query the device geometry and put it into the boot sector. * Map the file and put the map in the boot sector and file. @@ -1056,10 +1061,132 @@ static int ext_write_to_fs(ext2_file_t e2_file, const void *buf, size_t count, return done; } +/* Construct the boot file map */ +static int ext_construct_sectmap_fs(ext2_filsys fs, ext2_ino_t newino, + sector_t *sectors, int nsect) +{ +} + static int write_to_device(ext2_filsys fs, const char *filename, const char *str, int length, int i_flags, int devfd) { + ext2_ino_t newino; + ext2_ino_t root = EXT2_ROOT_INO; + struct ext2_inode inode; + int retval, i, modbytes, nsect; + ext2_file_t e2_file; + sector_t *sectors; + + + /* Remove it if it is already exists */ + retval = ext2fs_namei(fs, root, root, filename, &newino); + if (retval == 0) { + dprintf("%s: the file already exists: %s, removing it\n", + program, filename); + retval = ext2fs_unlink(fs, root, filename, newino, 0); + if (retval) { + fprintf(stderr, "%s: failed to unlink: %s\n", program, filename); + return retval; + } + } + + /* Create new inode */ + retval = ext2fs_new_inode(fs, root, 010755, 0, &newino); + if (retval) { + fprintf(stderr, "%s: ERROR: failed to create inode for: %s\n", + program, filename); + return retval; + } + + /* Link the inode and the filename */ + retval = ext2fs_link(fs, root, filename, newino, EXT2_FT_REG_FILE); + if (retval) { + fprintf(stderr, "%s: ERROR: failed to link inode for: %s.\n", + program, filename); + return retval; + } + + if (ext2fs_test_inode_bitmap2(fs->inode_map, newino)) + fprintf(stderr, "%s: warning: inode already set %s.\n", + program, filename); + + ext2fs_inode_alloc_stats2(fs, newino, +1, 0); + memset(&inode, 0, sizeof(inode)); + inode.i_mode = LINUX_S_IFREG | LINUX_S_IRUSR | LINUX_S_IRGRP + | LINUX_S_IROTH; + inode.i_flags |= i_flags; + inode.i_atime = inode.i_ctime = inode.i_mtime + fs->now ? fs->now : time(0); + inode.i_links_count = 1; + if (fs->super->s_feature_incompat & + EXT3_FEATURE_INCOMPAT_EXTENTS) { + struct ext3_extent_header *eh; + + eh = (struct ext3_extent_header *) &inode.i_block[0]; + eh->eh_depth = 0; + eh->eh_entries = 0; + eh->eh_magic = ext2fs_cpu_to_le16(EXT3_EXT_MAGIC); + i = (sizeof(inode.i_block) - sizeof(*eh)) / + sizeof(struct ext3_extent); + eh->eh_max = ext2fs_cpu_to_le16(i); + inode.i_flags |= EXT4_EXTENTS_FL; + } + + retval = ext2fs_write_new_inode(fs, newino, &inode); + if (retval) { + fprintf(stderr, "%s: ERROR: while writting inode %d.\n", + program, newino); + return 1; + } + + retval = ext2fs_file_open(fs, newino, EXT2_FILE_WRITE, &e2_file); + if (retval) { + fprintf(stderr, "%s: ERROR: failed to open %s.\n", + program, filename); + return 1; + } + + /* Write to file */ + if (ext_write_to_fs(e2_file, str, length, 0, filename) == -1) + goto fail; + + if (strcmp(filename, "ldlinux.sys") == 0) { + /* Write ADV */ + if (ext_write_to_fs(e2_file, syslinux_adv, 2 * ADV_SIZE, + boot_image_len, "ADV") == -1) + goto fail; + + /* Patch syslinux_bootsect */ + patch_syslinux_bootsect(devfd); + + /* Patch ldlinux.sys */ + dprintf("%s: patching ldlinux.sys\n", program); + nsect = (boot_image_len + SECTOR_SIZE - 1) >> SECTOR_SHIFT; + nsect += 2; /* Two sectors for the ADV */ + sectors = alloca(sizeof(sector_t) * nsect); + memset(sectors, 0, nsect * sizeof *sectors); + /* The sectors will be modified and used by syslinux_patch() */ + retval = ext_construct_sectmap_fs(fs, newino, sectors, nsect); + if (retval) + goto fail; + + /* Create the modified image in memory */ + modbytes = syslinux_patch(sectors, nsect, opt.stupid_mode, + opt.raid_mode, NULL, subvol); + + /* Rewrite the first modbytes of ldlinux.sys */ + if (ext_write_to_fs(e2_file, str, modbytes, 0, "modified ldlinux.sys") + == -1) { + fprintf(stderr, "%s: ERROR: failed to patch %s.\n", program, + filename); + goto fail; + } + } + +fail: + (void) ext2fs_file_close(e2_file); + return retval; } static int handle_adv_on_device(ext2_filsys fs, int update_only) -- 1.9.1
Robert Yang
2014-Dec-24 08:16 UTC
[syslinux] [PATCH 6/8] extlinux/main.c: implement patch_syslinux_bootsect()
Extract the related code from patch_file_and_bootblock() to patch_syslinux_bootsect(), so that both of dir and device target can use it. Signed-off-by: Robert Yang <liezhi.yang at windriver.com> --- extlinux/main.c | 63 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/extlinux/main.c b/extlinux/main.c index 99a078c..f46ba68 100644 --- a/extlinux/main.c +++ b/extlinux/main.c @@ -225,6 +225,37 @@ ok: /* Patch syslinux_bootsect */ static void patch_syslinux_bootsect(int devfd) { + uint64_t totalbytes, totalsectors; + struct hd_geometry geo; + struct fat_boot_sector *sbs; + + totalbytes = get_size(devfd); + get_geometry(devfd, totalbytes, &geo); + + if (opt.heads) + geo.heads = opt.heads; + if (opt.sectors) + geo.sectors = opt.sectors; + + /* Patch this into a fake FAT superblock. This isn't because + FAT is a good format in any way, it's because it lets the + early bootstrap share code with the FAT version. */ + dprintf("heads = %u, sect = %u\n", geo.heads, geo.sectors); + + sbs = (struct fat_boot_sector *)syslinux_bootsect; + + totalsectors = totalbytes >> SECTOR_SHIFT; + if (totalsectors >= 65536) { + set_16(&sbs->bsSectors, 0); + } else { + set_16(&sbs->bsSectors, totalsectors); + } + set_32(&sbs->bsHugeSectors, totalsectors); + + set_16(&sbs->bsBytesPerSec, SECTOR_SIZE); + set_16(&sbs->bsSecPerTrack, geo.sectors); + set_16(&sbs->bsHeads, geo.heads); + set_32(&sbs->bsHiddenSecs, geo.start); } /* @@ -237,11 +268,8 @@ static void patch_syslinux_bootsect(int devfd) static int patch_file_and_bootblock(int fd, const char *dir, int devfd) { struct stat dirst, xdst; - struct hd_geometry geo; sector_t *sectp; - uint64_t totalbytes, totalsectors; int nsect; - struct fat_boot_sector *sbs; char *dirpath, *subpath, *xdirpath; int rv; @@ -285,33 +313,8 @@ static int patch_file_and_bootblock(int fd, const char *dir, int devfd) /* Now subpath should contain the path relative to the fs base */ dprintf("subpath = %s\n", subpath); - totalbytes = get_size(devfd); - get_geometry(devfd, totalbytes, &geo); - - if (opt.heads) - geo.heads = opt.heads; - if (opt.sectors) - geo.sectors = opt.sectors; - - /* Patch this into a fake FAT superblock. This isn't because - FAT is a good format in any way, it's because it lets the - early bootstrap share code with the FAT version. */ - dprintf("heads = %u, sect = %u\n", geo.heads, geo.sectors); - - sbs = (struct fat_boot_sector *)syslinux_bootsect; - - totalsectors = totalbytes >> SECTOR_SHIFT; - if (totalsectors >= 65536) { - set_16(&sbs->bsSectors, 0); - } else { - set_16(&sbs->bsSectors, totalsectors); - } - set_32(&sbs->bsHugeSectors, totalsectors); - - set_16(&sbs->bsBytesPerSec, SECTOR_SIZE); - set_16(&sbs->bsSecPerTrack, geo.sectors); - set_16(&sbs->bsHeads, geo.heads); - set_32(&sbs->bsHiddenSecs, geo.start); + /* Patch syslinux_bootsect */ + patch_syslinux_bootsect(devfd); /* Construct the boot file map */ -- 1.9.1
Robert Yang
2014-Dec-24 08:16 UTC
[syslinux] [PATCH 7/8] extlinux/main.c: implement ext_construct_sectmap_fs()
Get the bmap and set the sectors, which is used by the write_to_device(). Signed-off-by: Robert Yang <liezhi.yang at windriver.com> --- extlinux/main.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/extlinux/main.c b/extlinux/main.c index f46ba68..efc6b8b 100644 --- a/extlinux/main.c +++ b/extlinux/main.c @@ -1064,10 +1064,59 @@ static int ext_write_to_fs(ext2_file_t e2_file, const void *buf, size_t count, return done; } +/* The file's block count */ +int block_count = 0; +static int get_block_count(ext2_filsys fs EXT2FS_ATTR((unused)), + blk64_t *blocknr EXT2FS_ATTR((unused)), + e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), + blk64_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *private EXT2FS_ATTR((unused))) +{ + block_count++; + return 0; +} + /* Construct the boot file map */ static int ext_construct_sectmap_fs(ext2_filsys fs, ext2_ino_t newino, sector_t *sectors, int nsect) { + blk64_t pblk, blksize, blk = 0; + sector_t sec; + int i, retval; + + blksize = fs->blocksize; + blksize >>= SECTOR_SHIFT; + + /* Get the total blocks no. */ + retval = ext2fs_block_iterate3(fs, newino, BLOCK_FLAG_READ_ONLY, + NULL, get_block_count, NULL); + if (retval) { + fprintf(stderr, "%s: ERROR: ext2fs_block_iterate3() failed.\n", program); + return -1; + } + + while (nsect) { + if (block_count-- == 0) + break; + + /* Get the physical block no. (bmap) */ + retval = ext2fs_bmap2(fs, newino, 0, 0, 0, blk, 0, &pblk); + if (retval) { + fprintf(stderr, "%s: ERROR: ext2fs_bmap2() failed.\n", program); + return -1; + } + + blk++; + sec = (sector_t)pblk * blksize; + for (i = 0; i < blksize; i++) { + *sectors++ = sec++; + if (! --nsect) + break; + } + } + + return 0; } static int write_to_device(ext2_filsys fs, const char *filename, -- 1.9.1
Robert Yang
2014-Dec-24 08:16 UTC
[syslinux] [PATCH 8/8] libinstaller/syslxopt.c: update the help text.
We support both device and directory as the target now. Signed-off-by: Robert Yang <liezhi.yang at windriver.com> --- libinstaller/syslxopt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libinstaller/syslxopt.c b/libinstaller/syslxopt.c index 3fc5519..d06719f 100644 --- a/libinstaller/syslxopt.c +++ b/libinstaller/syslxopt.c @@ -88,7 +88,7 @@ void __attribute__ ((noreturn)) usage(int rv, enum syslinux_mode mode) /* Mounted fs installation (extlinux) */ /* Actually extlinux can also use -d to provide a directory too... */ fprintf(stderr, - "Usage: %s [options] directory\n" + "Usage: %s [options] <directory|device>\n" " --device Force use of a specific block device (experts only)\n", program); break; -- 1.9.1
Ady
2014-Dec-24 10:47 UTC
[syslinux] [PATCH 0/8] extlinux: support unmounted ext2/3/4 filesystem
> Hello syslinux, > > Merry Christmas! These patches will make extlinux work with umounted > ext2/3/4 filesystem, for example: > > $ extlinux -i /dev/sdXN > or > $ extlinux -i file_block > > Also it can work with something like: > $ extlinux /dev/sdXN --reset-adv > or > $ extlinux file_block --reset-adv >Thank you. The 'extlinux' command supports several (mounted) filesystems, not only extN. This series of patches seems to be relevant for extN only. From users' perspective, for the same binary to have different capabilities depending on the filesystem in question could easily trigger misunderstandings and demand more resources for support and clarify/update documentation. The 'syslinux' command expects for the filesystem not to be mounted, and uses the corresponding device as argument. Users already have enough troubles with so-called "tutorials" about The Syslinux Project, misstating commands, mixing versions and what not.>From users' perspective, there is a chance that it would be easier tosee the 'syslinux' command supporting extN (in addition to FAT/NTFS) than to change how the 'extlinux' command is expected to work (for any other supported filesystem). This is only natural, considering that the SYSLINUX and EXTLINUX bootloaders have been merged since version 4.00. Could this feature be integrated to the 'syslinux' command(s), rather than to the 'extlinux' one? TIA, Ady.
Ady
2014-Dec-24 12:10 UTC
[syslinux] [PATCH 8/8] libinstaller/syslxopt.c: update the help text.
> We support both device and directory as the target now. > > Signed-off-by: Robert Yang <liezhi.yang at windriver.com> > --- > libinstaller/syslxopt.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/libinstaller/syslxopt.c b/libinstaller/syslxopt.c > index 3fc5519..d06719f 100644 > --- a/libinstaller/syslxopt.c > +++ b/libinstaller/syslxopt.c > @@ -88,7 +88,7 @@ void __attribute__ ((noreturn)) usage(int rv, enum syslinux_mode mode) > /* Mounted fs installation (extlinux) */ > /* Actually extlinux can also use -d to provide a directory too... */ > fprintf(stderr, > - "Usage: %s [options] directory\n" > + "Usage: %s [options] <directory|device>\n" > " --device Force use of a specific block device (experts only)\n", > program); > break; > -- > 1.9.1 > > _______________________________________________ > Syslinux mailing list > Submissions to Syslinux at zytor.com > Unsubscribe or set options at: > http://www.zytor.com/mailman/listinfo/syslinux >I would rather see extN support included in the 'syslinux' command(s), but if this feature is added to the 'extlinux' command as proposed in this series of patches, then the resulting usage would need to be more accurate. For example, something *similar* to: Usage: [options] directory Usage for ext2/3/4 only: [options] <directory|device> To be clear, the resulting output would need to be (at least) 2 different rows, instead of a generic uniform usage output. In case different capabilities per supported filesystem are added in the future, then more details would need to be added to the usage output, accordingly. Again, I would much rather see extN support added to the 'syslinux' command(s), instead of messing with the uniformity of the 'extlinux' installer. TIA, Ady.
Robert Yang
2014-Dec-24 14:38 UTC
[syslinux] [PATCH 0/8] extlinux: support unmounted ext2/3/4 filesystem
On 12/24/2014 06:47 PM, Ady wrote:> >> Hello syslinux, >> >> Merry Christmas! These patches will make extlinux work with umounted >> ext2/3/4 filesystem, for example: >> >> $ extlinux -i /dev/sdXN >> or >> $ extlinux -i file_block >> >> Also it can work with something like: >> $ extlinux /dev/sdXN --reset-adv >> or >> $ extlinux file_block --reset-adv >> > > Thank you. > > The 'extlinux' command supports several (mounted) filesystems, not only > extN. This series of patches seems to be relevant for extN only. From > users' perspective, for the same binary to have different capabilities > depending on the filesystem in question could easily trigger > misunderstandings and demand more resources for support and > clarify/update documentation. > > The 'syslinux' command expects for the filesystem not to be mounted, > and uses the corresponding device as argument. > > Users already have enough troubles with so-called "tutorials" about The > Syslinux Project, misstating commands, mixing versions and what not. > >>From users' perspective, there is a chance that it would be easier to > see the 'syslinux' command supporting extN (in addition to FAT/NTFS) > than to change how the 'extlinux' command is expected to work (for any > other supported filesystem). This is only natural, considering that the > SYSLINUX and EXTLINUX bootloaders have been merged since version 4.00. > > Could this feature be integrated to the 'syslinux' command(s), rather > than to the 'extlinux' one?Thanks for you reply, it makes things clear, yes, we should add it to syslinux rather than extlinux. I will add it to syslinux and send patches later. // Robert> > TIA, > Ady. > _______________________________________________ > Syslinux mailing list > Submissions to Syslinux at zytor.com > Unsubscribe or set options at: > http://www.zytor.com/mailman/listinfo/syslinux > >
H. Peter Anvin
2014-Dec-24 20:33 UTC
[syslinux] [PATCH 0/8] extlinux: support unmounted ext2/3/4 filesystem
On 12/24/2014 12:16 AM, Robert Yang wrote:> Hello syslinux, > > Merry Christmas! These patches will make extlinux work with umounted > ext2/3/4 filesystem, for example: > > $ extlinux -i /dev/sdXN > or > $ extlinux -i file_block > > Also it can work with something like: > $ extlinux /dev/sdXN --reset-adv > or > $ extlinux file_block --reset-adv > > We don't use a new option (I planed to use "-d" but it is already in > use), it will check whether the target is a directory or device and > decide what to do, it would stop and error if the device is mounted. > > I put these patches on github so that you can easily get them in case > you'd like to test them. (The repo's name is sys_tmp, which avoids > confusing others, I will remove the repo when these patches are > reviewed). > > More info: > * It will use libext2fs to read and write the file. > * It will be used when the target is a extX device or file block, and > work as before when the target is a directory. > * It will be used for both modifing the existing adv when > update_only == -1, and install the files to the filesystem. > > We will begin to use this feature in Yocto Project once it is fine to > the syslinux community. >I believe we should unify this with the syslinux installer, which is used for unmounted FAT filesystems. Ideally we should unify that with the extlinux installer too, but that may be a later project. -hpa
Robert Yang
2014-Dec-25 01:11 UTC
[syslinux] [PATCH 0/8] extlinux: support unmounted ext2/3/4 filesystem
On 12/25/2014 04:33 AM, H. Peter Anvin wrote:> On 12/24/2014 12:16 AM, Robert Yang wrote: >> Hello syslinux, >> >> Merry Christmas! These patches will make extlinux work with umounted >> ext2/3/4 filesystem, for example: >> >> $ extlinux -i /dev/sdXN >> or >> $ extlinux -i file_block >> >> Also it can work with something like: >> $ extlinux /dev/sdXN --reset-adv >> or >> $ extlinux file_block --reset-adv >> >> We don't use a new option (I planed to use "-d" but it is already in >> use), it will check whether the target is a directory or device and >> decide what to do, it would stop and error if the device is mounted. >> >> I put these patches on github so that you can easily get them in case >> you'd like to test them. (The repo's name is sys_tmp, which avoids >> confusing others, I will remove the repo when these patches are >> reviewed). >> >> More info: >> * It will use libext2fs to read and write the file. >> * It will be used when the target is a extX device or file block, and >> work as before when the target is a directory. >> * It will be used for both modifing the existing adv when >> update_only == -1, and install the files to the filesystem. >> >> We will begin to use this feature in Yocto Project once it is fine to >> the syslinux community. >> > > I believe we should unify this with the syslinux installer, which is > used for unmounted FAT filesystems. Ideally we should unify that withThanks, Ady also suggested this, I will add the patches to syslinux and send later. // Robert> the extlinux installer too, but that may be a later project. > > -hpa > > > >
Robert Yang
2014-Dec-25 02:32 UTC
[syslinux] [PATCH 0/8] extlinux: support unmounted ext2/3/4 filesystem
On 12/25/2014 04:33 AM, H. Peter Anvin wrote:> On 12/24/2014 12:16 AM, Robert Yang wrote: >> Hello syslinux, >> >> Merry Christmas! These patches will make extlinux work with umounted >> ext2/3/4 filesystem, for example: >> >> $ extlinux -i /dev/sdXN >> or >> $ extlinux -i file_block >> >> Also it can work with something like: >> $ extlinux /dev/sdXN --reset-adv >> or >> $ extlinux file_block --reset-adv >> >> We don't use a new option (I planed to use "-d" but it is already in >> use), it will check whether the target is a directory or device and >> decide what to do, it would stop and error if the device is mounted. >> >> I put these patches on github so that you can easily get them in case >> you'd like to test them. (The repo's name is sys_tmp, which avoids >> confusing others, I will remove the repo when these patches are >> reviewed). >> >> More info: >> * It will use libext2fs to read and write the file. >> * It will be used when the target is a extX device or file block, and >> work as before when the target is a directory. >> * It will be used for both modifing the existing adv when >> update_only == -1, and install the files to the filesystem. >> >> We will begin to use this feature in Yocto Project once it is fine to >> the syslinux community. >> > > I believe we should unify this with the syslinux installer, which is > used for unmounted FAT filesystems. Ideally we should unify that with > the extlinux installer too, but that may be a later project.Hello hpa, What does "unify that with the extlinux installer too" mean, please ? And I will add the patches to syslinux (not syslinux-mtools), and we don't require the root privilege if it is ext2/ext3/ext4 since it doesn't need mount, what's your opinion, please ? // Robert> > -hpa > > > >