[syslinux] [PATCH 5/8] extlinux/main.c: implement write_to_device()
Robert Yang
liezhi.yang at windriver.com
Wed Dec 24 00:16:12 PST 2014
* 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
More information about the Syslinux
mailing list