From c5e9d7a496936b9ea553be6fef4dff74596bbf11 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 15 Mar 2007 16:57:43 -0700 Subject: Library functions for manipulating initramfs Library support for constructing initramfs. This version is *not* complete, as it doesn't take into account alignment requirements properly. --- com32/lib/syslinux/initramfs_file.c | 154 ++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 com32/lib/syslinux/initramfs_file.c (limited to 'com32/lib/syslinux/initramfs_file.c') diff --git a/com32/lib/syslinux/initramfs_file.c b/com32/lib/syslinux/initramfs_file.c new file mode 100644 index 00000000..75b3f29f --- /dev/null +++ b/com32/lib/syslinux/initramfs_file.c @@ -0,0 +1,154 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * initramfs_file.c + * + * Utility functions to add arbitrary files including cpio header + */ + +#include +#include +#include +#include +#include + +#define CPIO_MAGIC "070701" +struct cpio_header { + char c_magic[6]; /* 070701 */ + char c_ino[8]; /* Inode number */ + char c_mode[8]; /* File mode and permissions */ + char c_uid[8]; /* uid */ + char c_gid[8]; /* gid */ + char c_nlink[8]; /* Number of links */ + char c_mtime[8]; /* Modification time */ + char c_filesize[8]; /* Size of data field */ + char c_maj[8]; /* File device major number */ + char c_min[8]; /* File device minor number */ + char c_rmaj[8]; /* Device node reference major number */ + char c_rmin[8]; /* Device node reference minor number */ + char c_namesize[8]; /* Length of filename including final \0 */ + char c_chksum[8]; /* Checksum if c_magic ends in 2 */ +}; + +static uint32_t next_ino = 1; + +/* Create cpio headers for the directory entries leading up to a file. + Returns the number of bytes; doesn't touch the buffer if too small. */ +static size_t initramfs_mkdirs(const char *filename, void *buffer, + size_t buflen) +{ + const char *p = filename; + char *bp = buffer; + int len; + size_t bytes = 0; + int pad; + + while ((p = strchr(p, '/'))) { + if (p != filename && p[-1] != '/') { + len = p-filename; + bytes += ((sizeof(struct cpio_header)+len+1)+3) & ~3; + } + p++; + } + + if (buflen >= bytes) { + p = filename; + while ((p = strchr(p, '/'))) { + if (p != filename && p[-1] != '/') { + len = p-filename; + bp += sprintf(bp, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x" + "%08x%08x%08x%08x", next_ino++, S_IFDIR|0755, + 0, 0, 1, 0, 0, 0, 1, 0, 1, len+1, 0); + memcpy(bp, filename, len); + bp += len; + pad = (-(sizeof(struct cpio_header)+len) & 3) + 1; + memset(bp, 0, pad); + bp += pad; + } + } + } + + return bytes; +} + +int initramfs_mknod(struct initramfs *ihead, const char *filename, + int do_mkdir, + uint16_t mode, size_t len, + uint32_t major, uint32_t minor) +{ + size_t bytes; + int namelen = strlen(filename); + int pad; + char *buffer, *bp; + + if (do_mkdir) + bytes = initramfs_mkdirs(filename, NULL, 0); + else + bytes = 0; + + bytes += ((sizeof(struct cpio_header)+namelen+1)+3) & ~3; + + bp = buffer = malloc(bytes); + if (!buffer) + return -1; + + if (do_mkdir) + bp += initramfs_mkdirs(filename, bp, bytes); + + bp += sprintf(bp, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x" + "%08x%08x%08x%08x", next_ino++, mode, + 0, 0, 1, 0, len, 0, 1, major, minor, len+1, 0); + memcpy(bp, filename, namelen); + bp += len; + pad = (-(sizeof(struct cpio_header)+namelen) & 3) + 1; + memset(bp, 0, pad); + + if (initramfs_add_data(ihead, buffer, bytes, bytes)) { + free(buffer); + return -1; + } + + return 0; +} + +int initramfs_add_file(struct initramfs *ihead, const void *data, + size_t data_len, size_t len, + const char *filename, int do_mkdir, uint32_t mode) +{ + if (initramfs_mknod(ihead, filename, do_mkdir, + (mode & S_IFMT) ? mode : mode|S_IFREG, + len, 0, 1)) + return -1; + + return initramfs_add_data(ihead, data, data_len, len); +} + +int initramfs_add_trailer(struct initramfs *ihead) +{ + return initramfs_mknod(ihead, "TRAILER!!!", 0, 0, 0, 0, 0); +} -- cgit v1.2.1