Library functions for manipulating initramfs
authorH. Peter Anvin <hpa@zytor.com>
Thu, 15 Mar 2007 23:57:43 +0000 (16:57 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Thu, 15 Mar 2007 23:57:43 +0000 (16:57 -0700)
Library support for constructing initramfs.  This version is *not*
complete, as it doesn't take into account alignment requirements
properly.

com32/include/syslinux/linux.h
com32/include/syslinux/loadfile.h [moved from com32/libutil/include/syslinux/loadfile.h with 100% similarity]
com32/lib/Makefile
com32/lib/syslinux/initramfs.c [new file with mode: 0644]
com32/lib/syslinux/initramfs_archive.c [new file with mode: 0644]
com32/lib/syslinux/initramfs_file.c [new file with mode: 0644]
com32/lib/syslinux/initramfs_loadfile.c [new file with mode: 0644]
com32/lib/syslinux/loadfile.c [moved from com32/libutil/syslinux/loadfile.c with 100% similarity]
com32/libutil/Makefile

index 821ef0a..69e2a3c 100644 (file)
@@ -45,7 +45,7 @@
 struct initramfs {
   struct initramfs *prev, *next;
   size_t len;
-  void *data;
+  const void *data;
   size_t data_len;
 };
 
@@ -55,4 +55,21 @@ int syslinux_boot_linux(void *kernel_buf, size_t kernel_size,
                        uint16_t video_mode,
                        uint32_t mem_limit);
 
+/* Initramfs manipulation functions */
+
+struct initramfs *initramfs_init(void);
+int initramfs_add_data(struct initramfs *ihead, const void *data,
+                      size_t data_len, size_t len);
+int initramfs_mknod(struct initramfs *ihead, const char *filename,
+                   int do_mkdir,
+                   uint16_t mode, size_t len,
+                   uint32_t major, uint32_t minor);
+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);
+int initramfs_load_file(struct initramfs *ihead, const char *src_filename,
+                       const char *dst_filename, int do_mkdir, uint32_t mode);
+int initramfs_add_trailer(struct initramfs *ihead);
+int initramfs_load_archive(struct initramfs *ihead, const char *filename);
+
 #endif /* _SYSLINUX_LINUX_H */
index 0ea60e7..d3bbb0a 100644 (file)
@@ -69,7 +69,10 @@ LIBOBJS = \
        syslinux/shuffle_rm.o syslinux/zonelist.o                       \
        syslinux/dump_mmap.o syslinux/dump_movelist.o                   \
        \
-       syslinux/load_linux.o                                           \
+       syslinux/loadfile.o                                             \
+       syslinux/load_linux.o syslinux/initramfs.o                      \
+       syslinux/initramfs_file.o syslinux/initramfs_loadfile.o         \
+       syslinux/initramfs_archive.o                                    \
        \
        syslinux/pxe_get_cached.o
 
diff --git a/com32/lib/syslinux/initramfs.c b/com32/lib/syslinux/initramfs.c
new file mode 100644 (file)
index 0000000..a3253a1
--- /dev/null
@@ -0,0 +1,68 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   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.c
+ *
+ * Utility functions for initramfs manipulation
+ */
+
+#include <stdlib.h>
+#include <syslinux/linux.h>
+
+struct initramfs *initramfs_init(void)
+{
+  struct initramfs *ir;
+
+  ir = calloc(sizeof(*ir), 1);
+  if (!ir)
+    return NULL;
+
+  ir->prev = ir->next = ir;
+  return ir;
+}
+
+int initramfs_add_data(struct initramfs *ihead, const void *data,
+                      size_t data_len, size_t len)
+{
+  struct initramfs *in;
+
+  in = malloc(sizeof(*in));
+  if (!in)
+    return -1;
+
+  in->len = len;
+  in->data = data;
+  in->data_len = data_len;
+
+  in->next = ihead;
+  in->prev = ihead->prev;
+  ihead->prev->next = in;
+  ihead->prev = in;
+
+  return 0;
+}
diff --git a/com32/lib/syslinux/initramfs_archive.c b/com32/lib/syslinux/initramfs_archive.c
new file mode 100644 (file)
index 0000000..903ef86
--- /dev/null
@@ -0,0 +1,47 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   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_archive.c
+ *
+ * Utility function to load an initramfs archive.
+ */
+
+#include <stdlib.h>
+#include <syslinux/loadfile.h>
+#include <syslinux/linux.h>
+
+int initramfs_load_archive(struct initramfs *ihead, const char *filename)
+{
+  void *data;
+  size_t len;
+
+  if (loadfile(filename, &data, &len))
+    return -1;
+
+  return initramfs_add_data(ihead, data, len, len);
+}
diff --git a/com32/lib/syslinux/initramfs_file.c b/com32/lib/syslinux/initramfs_file.c
new file mode 100644 (file)
index 0000000..75b3f29
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <syslinux/linux.h>
+
+#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);
+}
diff --git a/com32/lib/syslinux/initramfs_loadfile.c b/com32/lib/syslinux/initramfs_loadfile.c
new file mode 100644 (file)
index 0000000..de9c4bd
--- /dev/null
@@ -0,0 +1,48 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   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_loadfile.c
+ *
+ * Load a single file into an initramfs image.
+ */
+
+#include <syslinux/linux.h>
+#include <syslinux/loadfile.h>
+
+int initramfs_load_file(struct initramfs *ihead, const char *src_filename,
+                       const char *dst_filename, int do_mkdir, uint32_t mode)
+{
+  void *data;
+  size_t len;
+
+  if (loadfile(src_filename, &data, &len))
+    return -1;
+
+  return initramfs_add_file(ihead, data, len, len, dst_filename,
+                           do_mkdir, mode);
+}
index eaae415..7e5335f 100644 (file)
@@ -46,8 +46,7 @@ LNXCFLAGS  = -I./include -W -Wall -O -g
 LNXSFLAGS  = -g
 LNXLDFLAGS = -g
 OBJCOPY    = objcopy
-LIBOBJS           = ansiline.o ansiraw.o get_key.o idle.o sha1hash.o unbase64.o \
-            syslinux/loadfile.o
+LIBOBJS           = ansiline.o ansiraw.o get_key.o idle.o sha1hash.o unbase64.o
 LNXLIBOBJS = $(patsubst %.o,%.lo,$(LIBOBJS))
 
 .SUFFIXES: .lss .c .lo .o .elf .c32 .lnx