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:
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) {
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)
{
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) {
*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;
if (!opt.params)
opt.params = "";
- wrap_kernel(kernel, opt.params, ird, stdout);
+ wrap_kernel(kernel, opt.params, ird, out);
return 0;
}
--- /dev/null
+/* ----------------------------------------------------------------------- *
+ *
+ * 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;
+}
--- /dev/null
+/* ----------------------------------------------------------------------- *
+ *
+ * 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 */
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 */
#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;