Change the dump function to also be able to load a component.
authorThadeu Lima de Souza Cascardo <cascardo@cascardo.eti.br>
Thu, 27 Mar 2014 21:38:02 +0000 (18:38 -0300)
committerThadeu Lima de Souza Cascardo <cascardo@cascardo.eti.br>
Fri, 28 Mar 2014 02:35:26 +0000 (23:35 -0300)
It might be desirable to load a kernel and initrd and save it to a
bootimg. They need to be padded with zeroes to align to a page size.

Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@cascardo.eti.br>
bootimg.c

index 9ce6fb8..b015c10 100644 (file)
--- a/bootimg.c
+++ b/bootimg.c
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
+#include <sys/stat.h>
 
-static int dump(int fd, size_t len, int pgsz, char *fname)
+static int dump_or_load(int fd, size_t *len, int pgsz, char *fname, int dump)
 {
-       int out;
+       int cfd;
        char *page;
        int i, npages;
        int r;
+       int ifd, ofd;
+       int rem;
        page = malloc(pgsz);
        if (!page)
                return -ENOMEM;
-       out = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0644);
-       if (out < 0)
-               return -errno;
-       npages = (len + pgsz - 1) / pgsz;
+       if (dump)
+               cfd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0644);
+       else
+               cfd = open(fname, O_RDONLY);
+       if (cfd < 0)
+               goto out;
+       if (dump) {
+               ifd = fd;
+               ofd = cfd;
+       } else {
+               struct stat s;
+               r = fstat(cfd, &s);
+               if (r < 0) {
+                       goto out;
+               }
+               *len = s.st_size;
+               ifd = cfd;
+               ofd = fd;
+       }
+       npages = (*len + pgsz - 1) / pgsz;
        for (i = 1; i <= npages; i++) {
                if (i == npages) {
-                       len = len & (pgsz - 1);
-                       if (len > 0) {
-                               r = read(fd, page, len);
-                               if (r != len)
+                       rem = *len & (pgsz - 1);
+                       if (rem > 0) {
+                               r = read(ifd, page, rem);
+                               if (r != rem)
                                        goto out;
-                               r = write(out, page, len);
-                               if (r != len)
+                               r = write(ofd, page, rem);
+                               if (r != rem)
                                        goto out;
+                               /* Write padding */
+                               if (!dump) {
+                                       memset(page, 0, pgsz - rem);
+                                       write(ofd, page, pgsz - rem);
+                               }
                        }
                } else {
-                       r = read(fd, page, pgsz);
+                       r = read(ifd, page, pgsz);
                        if (r != pgsz)
                                goto out;
-                       r = write(out, page, pgsz);
+                       r = write(ofd, page, pgsz);
                        if (r != pgsz)
                                goto out;
                }
        }
        free(page);
-       close(out);
+       close(cfd);
        return 0;
 out:
        free(page);
-       close(out);
+       close(cfd);
        if (r < 0)
                return -errno;
        return -EINVAL;
 }
 
+static int dump(int fd, size_t len, int pgsz, char *fname)
+{
+       return dump_or_load(fd, &len, pgsz, fname, 1);
+}
+
+static int load(int fd, size_t *len, int pgsz, char *fname)
+{
+       return dump_or_load(fd, len, pgsz, fname, 0);
+}
+
 int main(int argc, char **argv)
 {
        int fd;