Add NBI support
authorH. Peter Anvin <hpa@zytor.com>
Fri, 4 Jan 2008 22:48:56 +0000 (14:48 -0800)
committerH. Peter Anvin <hpa@zytor.com>
Fri, 4 Jan 2008 22:48:56 +0000 (14:48 -0800)
Makefile
linux.c
main.c
nbi.c [new file with mode: 0644]
nbi.h [new file with mode: 0644]
segment.h
wraplinux.h

index 4902b09..013ea3e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -35,7 +35,7 @@ reloc/reloc.elf: $(RELOC_OBJS) reloc/reloc.ld
 
 reloc.o: reloc.S reloc/reloc.bin 
 
-wraplinux: main.o linux.o reloc.o elf.o segment.o
+wraplinux: main.o linux.o reloc.o elf.o nbi.o segment.o
        $(CC) $(LDFLAGS) -o $@ $^
 
 clean:
diff --git a/linux.c b/linux.c
index 28f8cf1..93fd62e 100644 (file)
--- a/linux.c
+++ b/linux.c
@@ -229,7 +229,7 @@ int wrap_kernel(const char *kernel_file, const char *cmdline,
   wrle32(ssup.address, &info->setup_addr);
   wrle32(scmd.address, &info->cmdline_addr);
 
-  rv = output_elf(&srel, srel.address + sizeof *info, out);
+  rv = opt.output(&srel, srel.address + sizeof *info, out);
 
  err:
   if (ird) {
diff --git a/main.c b/main.c
index 3972ae9..4262d67 100644 (file)
--- a/main.c
+++ b/main.c
 
 const char *program;
 
-struct opt {
-  const char *params;
-} opt;
-
 const struct option long_options[] = {
   { "params",          1, 0, 'p' },
+  { "cmdline",         1, 0, 'p' },
+  { "commandline",     1, 0, 'p' },
   { "initrd",          1, 0, 'i' },
+  { "output",          1, 0, 'o' },
+  { "elf",             0, 0, 'E' },
+  { "nbi",             0, 0, 'N' },
   { 0, 0, 0, 0 }
 };
-#define OPTSTRING "p:i:"
+#define OPTSTRING "p:i:o:EN"
 
 static void usage(int err)
 {
@@ -51,9 +52,12 @@ int main(int argc, char *argv[])
   int optch;
   const char *kernel;
   struct string_list *ird = NULL, **irdp = &ird, *ip;
+  FILE *out = stdout;
 
   program = argv[0];
 
+  opt.output = output_elf;
+
   while ( (optch = getopt_long(argc, argv, OPTSTRING, long_options, NULL))
          != EOF ) {
     switch (optch) {
@@ -67,6 +71,19 @@ int main(int argc, char *argv[])
       *irdp = ip;
       irdp = &ip->next;
       break;
+    case 'o':
+      out = fopen(optarg, "w");
+      if (!out) {
+       perror(optarg);
+       exit(EX_CANTCREAT);
+      }
+      break;
+    case 'E':
+      opt.output = output_elf;
+      break;
+    case 'N':
+      opt.output = output_nbi;
+      break;
     default:
       usage(EX_USAGE);
       break;
@@ -81,7 +98,7 @@ int main(int argc, char *argv[])
   if (!opt.params)
     opt.params = "";
 
-  wrap_kernel(kernel, opt.params, ird, stdout);
+  wrap_kernel(kernel, opt.params, ird, out);
   return 0;
 }
 
diff --git a/nbi.c b/nbi.c
new file mode 100644 (file)
index 0000000..eaaaf9b
--- /dev/null
+++ b/nbi.c
@@ -0,0 +1,70 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2008 H. Peter Anvin - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ *   Boston MA 02110-1301, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * nbi.c
+ *
+ * Take a linked list of segments and output it as an NBI image
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include "nbi.h"
+#include "segment.h"
+#include "le.h"
+
+int output_nbi(struct segment *segs, addr_t entry, FILE *out)
+{
+       struct nbi_header nhdr;
+       struct nbi_image_header ihdr;
+       uint32_t offset;
+       struct segment *s;
+
+       wrle32(NBI_MAGIC, &nhdr.magic);
+       wrle32(NBI_HFLAG_PROTMODE + (sizeof nhdr >> 2), &nhdr.flags);
+       wrle32(entry, &nhdr.entry);
+
+       /* NBI wants a 512-byte area to load its header into memory. */
+       /* This kind of sucks for that purpose, but what to do... */
+       wrle16(0x7c00, &nhdr.header_off);
+       wrle16(0, &nhdr.header_seg);
+
+       fwrite(&nhdr, 1, sizeof nhdr, out);
+       offset = sizeof nhdr;
+
+       for (s = segs; s; s = s->next) {
+               ihdr.lengths = sizeof ihdr >> 2;
+               ihdr.tags = 0;
+               ihdr.resv = 0;
+               ihdr.flags = s->next ? 0 : NBI_IFLAG_LAST;
+               ihdr.load_addr = s->address;
+               ihdr.filesz = s->length;
+               ihdr.memsz  = s->length;
+       
+               fwrite(&ihdr, 1, sizeof ihdr, out);
+               offset += sizeof ihdr;
+       }
+
+       while (offset < NBI_HEADER_SIZE) {
+               putc(0, out);
+               offset++;
+       }
+       putc(0x55, out);
+       putc(0xaa, out);
+
+       for (s = segs; s; s = s->next)
+               fwrite(s->data, 1, s->length, out);
+
+       return 0;
+}
diff --git a/nbi.h b/nbi.h
new file mode 100644 (file)
index 0000000..5fc3fc7
--- /dev/null
+++ b/nbi.h
@@ -0,0 +1,52 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2008 H. Peter Anvin - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ *   Boston MA 02110-1301, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * nbi.h
+ *
+ * NBI format definition, written from spec
+ */
+
+#ifndef NBI_H
+#define NBI_H
+
+#include <stdint.h>
+
+#define NBI_MAGIC 0x1b031336
+
+struct nbi_header {
+  uint32_t magic;
+  uint32_t flags;
+  uint16_t header_off, header_seg;
+  uint32_t entry;
+};
+
+#define NBI_HFLAG_RETURN       0x00000100
+#define NBI_HFLAG_PROTMODE     0x80000000
+
+struct nbi_image_header {
+  uint8_t  lengths;
+  uint8_t  tags;
+  uint8_t  resv;
+  uint8_t  flags;
+  uint32_t load_addr;
+  uint32_t filesz;
+  uint32_t memsz;
+};
+
+#define NBI_IFLAG_ADDR_LAST    0x01
+#define NBI_IFLAG_ADDR_END     0x02
+#define NBI_IFLAG_LAST         0x04
+
+#define NBI_HEADER_SIZE                510
+
+#endif /* NBI_H */
index bac5f03..1da4666 100644 (file)
--- a/segment.h
+++ b/segment.h
@@ -37,5 +37,6 @@ struct segment {
 
 struct segment *sort_segments(struct segment *list);
 int output_elf(struct segment *segs, addr_t entry, FILE *out);
+int output_nbi(struct segment *segs, addr_t entry, FILE *out);
 
 #endif /* SEGMENT_H */
index 6fa5fdb..280dd48 100644 (file)
 #define WRAPLINUX_H
 
 #include <stdio.h>
+#include "segment.h"
+
+extern const char *program;
+
+struct opt {
+  const char *params;
+  int (*output)(struct segment *, addr_t, FILE *);
+} opt;
 
 struct string_list {
   struct string_list *next;