diff options
Diffstat (limited to 'util/mkelfImage/main')
-rw-r--r-- | util/mkelfImage/main/Makefile | 18 | ||||
-rw-r--r-- | util/mkelfImage/main/mkelfImage.c | 663 | ||||
-rw-r--r-- | util/mkelfImage/main/mkelfImage.man | 166 |
3 files changed, 847 insertions, 0 deletions
diff --git a/util/mkelfImage/main/Makefile b/util/mkelfImage/main/Makefile new file mode 100644 index 0000000000..403b0a4245 --- /dev/null +++ b/util/mkelfImage/main/Makefile @@ -0,0 +1,18 @@ +MKELF_OBJS=$(OBJDIR)/main/mkelfImage.o \ + $(OBJDIR)/linux-i386/mkelf-linux-i386.o \ + $(OBJDIR)/linux-ia64/mkelf-linux-ia64.o + +$(OBJDIR)/sbin/mkelfImage: $(MKELF_OBJS) $(DEPS) + $(MKDIR) -p $(@D) + $(HOST_CC) $(HOST_CFLAGS) $(MKELF_OBJS) -o $@ $(LIBS) + +$(OBJDIR)/main/mkelfImage.o: main/mkelfImage.c include/mkelfImage.h $(DEPS) + $(MKDIR) -p $(@D) + $(HOST_CC) $(HOST_CFLAGS) -c $< -o $@ + +$(OBJDIR)/man/man8/mkelfImage.8: main/mkelfImage.man + $(MKDIR) -p $(@D) + $(SED) \ + -e 's,^.TH MKELFIMAGE 8 "RELEASE_DATE" "VERSION"$$,.TH MKELFIMAGE 8 "$(RELEASE_DATE)" "$(VERSION)",' \ + $< > $@ + $(CP) $< $@ diff --git a/util/mkelfImage/main/mkelfImage.c b/util/mkelfImage/main/mkelfImage.c new file mode 100644 index 0000000000..bb318b3f37 --- /dev/null +++ b/util/mkelfImage/main/mkelfImage.c @@ -0,0 +1,663 @@ +#include <stdarg.h> +#include <errno.h> +#include <string.h> +#include <stdint.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <getopt.h> +#ifdef HAVE_ZLIB_H +#include <zlib.h> +#endif +#include "elf.h" +#include "elf_boot.h" +#include "mkelfImage.h" + +static struct file_type file_type[] = { + { "linux-i386", linux_i386_probe, linux_i386_mkelf, linux_i386_usage }, + { "bzImage-i386", bzImage_i386_probe, linux_i386_mkelf, linux_i386_usage }, + { "vmlinux-i386", vmlinux_i386_probe, linux_i386_mkelf, linux_i386_usage }, + { "linux-ia64", linux_ia64_probe, linux_ia64_mkelf, linux_ia64_usage }, +}; +static const int file_types = sizeof(file_type)/sizeof(file_type[0]); + +void die(char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + exit(1); +} + + + +/************************************************************************** +IPCHKSUM - Checksum IP Header +**************************************************************************/ +uint16_t ipchksum(const void *data, unsigned long length) +{ + unsigned long sum; + unsigned long i; + const uint8_t *ptr; + + /* In the most straight forward way possible, + * compute an ip style checksum. + */ + sum = 0; + ptr = data; + for(i = 0; i < length; i++) { + unsigned long value; + value = ptr[i]; + if (i & 1) { + value <<= 8; + } + /* Add the new value */ + sum += value; + /* Wrap around the carry */ + if (sum > 0xFFFF) { + sum = (sum + (sum >> 16)) & 0xFFFF; + } + } + return (~cpu_to_le16(sum)) & 0xFFFF; +} + +uint16_t add_ipchksums(unsigned long offset, uint16_t sum, uint16_t new) +{ + unsigned long checksum; + sum = ~sum & 0xFFFF; + new = ~new & 0xFFFF; + if (offset & 1) { + /* byte swap the sum if it came from an odd offset + * since the computation is endian independant this + * works. + */ + new = bswap_16(new); + } + checksum = sum + new; + if (checksum > 0xFFFF) { + checksum -= 0xFFFF; + } + return (~checksum) & 0xFFFF; +} + +void *xmalloc(size_t size, const char *name) +{ + void *buf; + buf = malloc(size); + if (!buf) { + die("Cannot malloc %ld bytes to hold %s: %s\n", + size + 0UL, name, strerror(errno)); + } + return buf; +} + +void *xrealloc(void *ptr, size_t size, const char *name) +{ + void *buf; + buf = realloc(ptr, size); + if (!buf) { + die("Cannot realloc %ld bytes to hold %s: %s\n", + size + 0UL, name, strerror(errno)); + } + return buf; +} + + +char *slurp_file(const char *filename, off_t *r_size) +{ + int fd; + char *buf; + off_t size, progress; + ssize_t result; + struct stat stats; + + + if (!filename) { + *r_size = 0; + return 0; + } + fd = open(filename, O_RDONLY); + if (fd < 0) { + die("Cannot open `%s': %s\n", + filename, strerror(errno)); + } + result = fstat(fd, &stats); + if (result < 0) { + die("Cannot stat: %s: %s\n", + filename, strerror(errno)); + } + size = stats.st_size; + *r_size = size; + buf = xmalloc(size, filename); + progress = 0; + while(progress < size) { + result = read(fd, buf + progress, size - progress); + if (result < 0) { + if ((errno == EINTR) || (errno == EAGAIN)) + continue; + die("read on %s of %ld bytes failed: %s\n", + filename, (size - progress)+ 0UL, strerror(errno)); + } + progress += result; + } + result = close(fd); + if (result < 0) { + die("Close of %s failed: %s\n", + filename, strerror(errno)); + } + return buf; +} + +#if HAVE_ZLIB_H +char *slurp_decompress_file(const char *filename, off_t *r_size) +{ + gzFile fp; + int errnum; + const char *msg; + char *buf; + off_t size, allocated; + ssize_t result; + + if (!filename) { + *r_size = 0; + return 0; + } + fp = gzopen(filename, "rb"); + if (fp == 0) { + msg = gzerror(fp, &errnum); + if (errnum == Z_ERRNO) { + msg = strerror(errno); + } + die("Cannot open `%s': %s\n", filename, msg); + } + size = 0; + allocated = 65536; + buf = xmalloc(allocated, filename); + do { + if (size == allocated) { + allocated <<= 1; + buf = xrealloc(buf, allocated, filename); + } + result = gzread(fp, buf + size, allocated - size); + if (result < 0) { + if ((errno == EINTR) || (errno == EAGAIN)) + continue; + + msg = gzerror(fp, &errnum); + if (errnum == Z_ERRNO) { + msg = strerror(errno); + } + die ("read on %s of %ld bytes failed: %s\n", + filename, (allocated - size) + 0UL, msg); + } + size += result; + } while(result > 0); + result = gzclose(fp); + if (result != Z_OK) { + msg = gzerror(fp, &errnum); + if (errnum == Z_ERRNO) { + msg = strerror(errno); + } + die ("Close of %s failed: %s\n", filename, msg); + } + *r_size = size; + return buf; +} +#else +char *slurp_decompress_file(const char *filename, off_t *r_size) +{ + return slurp_file(filename, r_size); +} +#endif + +struct memelfphdr *add_program_headers(struct memelfheader *ehdr, int count) +{ + struct memelfphdr *phdr; + int i; + ehdr->e_phnum = count; + ehdr->e_phdr = phdr = xmalloc(count *sizeof(*phdr), "Program headers"); + /* Set the default values */ + for(i = 0; i < count; i++) { + phdr[i].p_type = PT_LOAD; + phdr[i].p_flags = PF_R | PF_W | PF_X; + phdr[i].p_vaddr = 0; + phdr[i].p_paddr = 0; + phdr[i].p_filesz = 0; + phdr[i].p_memsz = 0; + phdr[i].p_data = 0; + } + return phdr; +} + +struct memelfnote *add_notes(struct memelfheader *ehdr, int count) +{ + struct memelfnote *notes; + ehdr->e_notenum = count; + ehdr->e_notes = notes = xmalloc(count *sizeof(*notes), "Notes"); + memset(notes, 0, count *sizeof(*notes)); + return notes; +} + +static int sizeof_notes(struct memelfnote *note, int notes) +{ + int size; + int i; + + size = 0; + for(i = 0; i < notes; i++) { + size += sizeof(Elf_Nhdr); + size += roundup(strlen(note[i].n_name)+1, 4); + size += roundup(note[i].n_descsz, 4); + } + return size; +} + +static uint16_t cpu_to_elf16(struct memelfheader *ehdr, uint16_t val) +{ + if (ehdr->ei_data == ELFDATA2LSB) { + return cpu_to_le16(val); + } + else if (ehdr->ei_data == ELFDATA2MSB) { + return cpu_to_be16(val); + } + die("Uknown elf layout in cpu_to_elf16"); + return 0; +} + +static uint32_t cpu_to_elf32(struct memelfheader *ehdr, uint32_t val) +{ + if (ehdr->ei_data == ELFDATA2LSB) { + return cpu_to_le32(val); + } + else if (ehdr->ei_data == ELFDATA2MSB) { + return cpu_to_be32(val); + } + die("Uknown elf layout in cpu_to_elf32"); + return 0; +} + +static uint64_t cpu_to_elf64(struct memelfheader *ehdr, uint64_t val) +{ + if (ehdr->ei_data == ELFDATA2LSB) { + return cpu_to_le64(val); + } + else if (ehdr->ei_data == ELFDATA2MSB) { + return cpu_to_be64(val); + } + die("Uknown elf layout in cpu_to_elf64"); + return 0; +} + +static void serialize_notes(char *buf, struct memelfheader *ehdr) +{ + struct Elf_Nhdr hdr; + struct memelfnote *note; + int notes; + size_t size, offset; + int i; + + /* Clear the buffer */ + note = ehdr->e_notes; + notes = ehdr->e_notenum; + size = sizeof_notes(note, notes); + memset(buf, 0, size); + + /* Write the Elf Notes */ + offset = 0; + for(i = 0; i < notes; i++) { + /* Compute the note header */ + size_t n_namesz; + n_namesz = strlen(note[i].n_name) +1; + hdr.n_namesz = cpu_to_elf32(ehdr, n_namesz); + hdr.n_descsz = cpu_to_elf32(ehdr, note[i].n_descsz); + hdr.n_type = cpu_to_elf32(ehdr, note[i].n_type); + + /* Copy the note into the buffer */ + memcpy(buf + offset, &hdr, sizeof(hdr)); + offset += sizeof(hdr); + memcpy(buf + offset, note[i].n_name, n_namesz); + offset += roundup(n_namesz, 4); + memcpy(buf + offset, note[i].n_desc, note[i].n_descsz); + offset += roundup(note[i].n_descsz, 4); + + } +} +static void serialize_ehdr(char *buf, struct memelfheader *ehdr) +{ + if (ehdr->ei_class == ELFCLASS32) { + Elf32_Ehdr *hdr = (Elf32_Ehdr *)buf; + hdr->e_ident[EI_MAG0] = ELFMAG0; + hdr->e_ident[EI_MAG1] = ELFMAG1; + hdr->e_ident[EI_MAG2] = ELFMAG2; + hdr->e_ident[EI_MAG3] = ELFMAG3; + hdr->e_ident[EI_CLASS] = ehdr->ei_class; + hdr->e_ident[EI_DATA] = ehdr->ei_data; + hdr->e_ident[EI_VERSION] = EV_CURRENT; + hdr->e_type = cpu_to_elf16(ehdr, ehdr->e_type); + hdr->e_machine = cpu_to_elf16(ehdr, ehdr->e_machine); + hdr->e_version = cpu_to_elf32(ehdr, EV_CURRENT); + hdr->e_entry = cpu_to_elf32(ehdr, ehdr->e_entry); + hdr->e_phoff = cpu_to_elf32(ehdr, sizeof(*hdr)); + hdr->e_shoff = cpu_to_elf32(ehdr, 0); + hdr->e_flags = cpu_to_elf32(ehdr, ehdr->e_flags); + hdr->e_ehsize = cpu_to_elf16(ehdr, sizeof(*hdr)); + hdr->e_phentsize = cpu_to_elf16(ehdr, sizeof(Elf32_Phdr)); + hdr->e_phnum = cpu_to_elf16(ehdr, ehdr->e_phnum); + hdr->e_shentsize = cpu_to_elf16(ehdr, 0); + hdr->e_shnum = cpu_to_elf16(ehdr, 0); + hdr->e_shstrndx = cpu_to_elf16(ehdr, 0); + } + else if (ehdr->ei_class == ELFCLASS64) { + Elf64_Ehdr *hdr = (Elf64_Ehdr *)buf; + hdr->e_ident[EI_MAG0] = ELFMAG0; + hdr->e_ident[EI_MAG1] = ELFMAG1; + hdr->e_ident[EI_MAG2] = ELFMAG2; + hdr->e_ident[EI_MAG3] = ELFMAG3; + hdr->e_ident[EI_CLASS] = ehdr->ei_class; + hdr->e_ident[EI_DATA] = ehdr->ei_data; + hdr->e_ident[EI_VERSION] = EV_CURRENT; + hdr->e_type = cpu_to_elf16(ehdr, ehdr->e_type); + hdr->e_machine = cpu_to_elf16(ehdr, ehdr->e_machine); + hdr->e_version = cpu_to_elf32(ehdr, EV_CURRENT); + hdr->e_entry = cpu_to_elf64(ehdr, ehdr->e_entry); + hdr->e_phoff = cpu_to_elf64(ehdr, sizeof(*hdr)); + hdr->e_shoff = cpu_to_elf64(ehdr, 0); + hdr->e_flags = cpu_to_elf32(ehdr, ehdr->e_flags); + hdr->e_ehsize = cpu_to_elf16(ehdr, sizeof(*hdr)); + hdr->e_phentsize = cpu_to_elf16(ehdr, sizeof(Elf64_Phdr)); + hdr->e_phnum = cpu_to_elf16(ehdr, ehdr->e_phnum); + hdr->e_shentsize = cpu_to_elf16(ehdr, 0); + hdr->e_shnum = cpu_to_elf16(ehdr, 0); + hdr->e_shstrndx = cpu_to_elf16(ehdr, 0); + } + else die("Uknown elf class: %x\n", ehdr->ei_class); +} +static void serialize_phdrs(char *buf, struct memelfheader *ehdr, size_t note_size) +{ + int i; + size_t offset, note_offset; + if (ehdr->ei_class == ELFCLASS32) { + Elf32_Phdr *phdr = (Elf32_Phdr *)buf; + note_offset = + sizeof(Elf32_Ehdr) + (sizeof(Elf32_Phdr)*ehdr->e_phnum); + offset = note_offset + note_size; + for(i = 0; i < ehdr->e_phnum; i++) { + struct memelfphdr *hdr = ehdr->e_phdr + i; + phdr[i].p_type = cpu_to_elf32(ehdr, hdr->p_type); + phdr[i].p_offset = cpu_to_elf32(ehdr, offset); + phdr[i].p_vaddr = cpu_to_elf32(ehdr, hdr->p_vaddr); + phdr[i].p_paddr = cpu_to_elf32(ehdr, hdr->p_paddr); + phdr[i].p_filesz = cpu_to_elf32(ehdr, hdr->p_filesz); + phdr[i].p_memsz = cpu_to_elf32(ehdr, hdr->p_memsz); + phdr[i].p_flags = cpu_to_elf32(ehdr, hdr->p_flags); + phdr[i].p_align = cpu_to_elf32(ehdr, 0); + if (phdr[i].p_type == PT_NOTE) { + phdr[i].p_filesz = cpu_to_elf32(ehdr, note_size); + phdr[i].p_memsz = cpu_to_elf32(ehdr, note_size); + phdr[i].p_offset = cpu_to_elf32(ehdr, note_offset); + } else { + offset += hdr->p_filesz; + } + } + } + else if (ehdr->ei_class == ELFCLASS64) { + Elf64_Phdr *phdr = (Elf64_Phdr *)buf; + note_offset = + sizeof(Elf64_Ehdr) + (sizeof(Elf64_Phdr)*ehdr->e_phnum); + offset = note_offset + note_size; + for(i = 0; i < ehdr->e_phnum; i++) { + struct memelfphdr *hdr = ehdr->e_phdr + i; + phdr[i].p_type = cpu_to_elf32(ehdr, hdr->p_type); + phdr[i].p_flags = cpu_to_elf32(ehdr, hdr->p_flags); + phdr[i].p_offset = cpu_to_elf64(ehdr, offset); + phdr[i].p_vaddr = cpu_to_elf64(ehdr, hdr->p_vaddr); + phdr[i].p_paddr = cpu_to_elf64(ehdr, hdr->p_paddr); + phdr[i].p_filesz = cpu_to_elf64(ehdr, hdr->p_filesz); + phdr[i].p_memsz = cpu_to_elf64(ehdr, hdr->p_memsz); + phdr[i].p_align = cpu_to_elf64(ehdr, 0); + if (phdr[i].p_type == PT_NOTE) { + phdr[i].p_filesz = cpu_to_elf64(ehdr, note_size); + phdr[i].p_memsz = cpu_to_elf64(ehdr, note_size); + phdr[i].p_offset = cpu_to_elf64(ehdr, note_offset); + } else { + offset += hdr->p_filesz; + } + } + } + else { + die("Unknwon elf class: %x\n", ehdr->ei_class); + } +} + +static void write_buf(int fd, char *buf, size_t size) +{ + size_t progress = 0; + ssize_t result; + while(progress < size) { + result = write(fd, buf + progress, size - progress); + if (result < 0) { + if ((errno == EAGAIN) || (errno == EINTR)) { + continue; + } + die ("write of %ld bytes failed: %s\n", + size - progress, strerror(errno)); + } + progress += result; + } +} +static void write_elf(struct memelfheader *ehdr, char *output) +{ + size_t ehdr_size; + size_t phdr_size; + size_t note_size; + size_t size; + uint16_t checksum; + size_t bytes; + char *buf; + int result, fd; + int i; + /* Prep for adding the checksum */ + for(i = 0; i < ehdr->e_notenum; i++) { + if ((memcmp(ehdr->e_notes[i].n_name, "ELFBoot", 8) == 0) && + (ehdr->e_notes[i].n_type == EIN_PROGRAM_CHECKSUM)) { + ehdr->e_notes[i].n_desc = &checksum; + ehdr->e_notes[i].n_descsz = 2; + } + } + /* Compute the sizes */ + ehdr_size = 0; + phdr_size = 0; + note_size = 0; + if (ehdr->e_notenum) { + note_size = sizeof_notes(ehdr->e_notes, ehdr->e_notenum); + } + if (ehdr->ei_class == ELFCLASS32) { + ehdr_size = sizeof(Elf32_Ehdr); + phdr_size = sizeof(Elf32_Phdr) * ehdr->e_phnum; + } + else if (ehdr->ei_class == ELFCLASS64) { + ehdr_size = sizeof(Elf64_Ehdr); + phdr_size = sizeof(Elf64_Phdr) * ehdr->e_phnum; + } + else { + die("Unknown elf class: %x\n", ehdr->ei_class); + } + + /* Allocate a buffer to temporarily hold the serialized forms */ + size = ehdr_size + phdr_size + note_size; + buf = xmalloc(size, "Elf Headers"); + memset(buf, 0, size); + serialize_ehdr(buf, ehdr); + serialize_phdrs(buf + ehdr_size, ehdr, note_size); + + /* Compute the checksum... */ + checksum = ipchksum(buf, ehdr_size + phdr_size); + bytes = ehdr_size + phdr_size; + for(i = 0; i < ehdr->e_phnum; i++) { + checksum = add_ipchksums(bytes, checksum, + ipchksum(ehdr->e_phdr[i].p_data, ehdr->e_phdr[i].p_filesz)); + bytes += ehdr->e_phdr[i].p_memsz; + } + + /* Compute the final form of the notes */ + serialize_notes(buf + ehdr_size + phdr_size, ehdr); + + /* Now write the elf image */ + fd = open(output, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IRGRP | S_IROTH); + if (fd < 0) { + die("Cannot open ``%s'':%s\n", + output, strerror(errno)); + } + write_buf(fd, buf, size); + for(i = 0; i < ehdr->e_phnum; i++) { + write_buf(fd, ehdr->e_phdr[i].p_data, ehdr->e_phdr[i].p_filesz); + } + result = close(fd); + if (result < 0) { + die("Close on %s failed: %s\n", + output, strerror(errno)); + } +} + +static void version(void) +{ + printf("mkelfImage " VERSION " released " RELEASE_DATE "\n"); +} +void usage(void) +{ + int i; + version(); + printf( + "Usage: mkelfImage [OPTION]... <kernel> <elf_kernel>\n" + "Build an ELF bootable kernel image from a normal kernel image\n" + "\n" + " -h, --help Print this help.\n" + " -v, --version Print the version of kexec.\n" + " --kernel=<filename> Set the kernel to <filename>\n" + " --output=<filename> Output to <filename>\n" + " -t, --type=TYPE Specify the new kernel is of <type>.\n" + "\n" + "Supported kernel types: \n" + ); + for(i = 0; i < file_types; i++) { + printf("%s\n", file_type[i].name); + file_type[i].usage(); + } + printf("\n"); +} + +void error(char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + usage(); + exit(1); +} + +int main(int argc, char **argv) +{ + int opt; + int fileind; + char *type, *kernel, *output; + off_t kernel_size; + char *kernel_buf; + int result; + int i; + struct memelfheader hdr; + + static const struct option options[] = { + MKELF_OPTIONS + { 0, 0, 0, 0 }, + }; + static const char short_options[] = MKELF_OPT_STR; + + memset(&hdr, 0, sizeof(hdr)); + kernel = 0; + output = 0; + + /* Get the default type from the program name */ + type = strrchr(argv[0], '/'); + if (!type) type = argv[0]; + if (memcmp(type, "mkelf-", 6) == 0) { + type = type + 6; + } else { + type = 0; + } + opterr = 0; /* Don't complain about unrecognized options here */ + while ((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) { + switch(opt) { + case OPT_HELP: + usage(); + return 0; + case OPT_VERSION: + version(); + return 0; + case OPT_KERNEL: + kernel = optarg; + break; + case OPT_OUTPUT: + output = optarg; + break; + case OPT_TYPE: + type = optarg; + break; + default: + break; + } + } + fileind = optind; + + /* Reset getopt for the next pass */ + opterr = 1; + optind = 1; + + if (argc - fileind > 0) { + kernel = argv[fileind++]; + } + if (argc - fileind > 0) { + output = argv[fileind++]; + } + if (!kernel) { + error("No kernel specified!\n"); + } + if (!output) { + error("No output file specified!\n"); + } + if (argc - fileind > 0) { + error("%d extra options specified!\n", argc - fileind); + } + + /* slurp in the input kernel */ + kernel_buf = slurp_decompress_file(kernel, &kernel_size); + + /* Find/verify the kernel type */ + for(i = 0; i < file_types; i++) { + char *reason; + if (type && (strcmp(type, file_type[i].name) != 0)) { + continue; + } + reason = file_type[i].probe(kernel_buf, kernel_size); + if (reason == 0) { + break; + } + if (type) { + die("Not %s: %s\n", type, reason); + } + } + if (i == file_types) { + die("Can not determine the file type of %s\n", kernel); + } + result = file_type[i].mkelf(argc, argv, &hdr, kernel_buf, kernel_size); + if (result < 0) { + die("Cannot create %s result: %d\n", output, result); + } + /* open the output file */ + write_elf(&hdr, output); + return 0; +} diff --git a/util/mkelfImage/main/mkelfImage.man b/util/mkelfImage/main/mkelfImage.man new file mode 100644 index 0000000000..f3f50d56d0 --- /dev/null +++ b/util/mkelfImage/main/mkelfImage.man @@ -0,0 +1,166 @@ +.\" Automatically generated by Pod::Man v1.3, Pod::Parser v1.13 +.\" But now manually maintained +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sh \" Subsection heading +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R + +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. | will give a +.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to +.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' +.\" expand to `' in nroff, nothing in troff, for use with C<>. +.tr \(*W-|\(bv\*(Tr +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.\" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.hy 0 +.if n .na +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "MKELFIMAGE 8" +.TH MKELFIMAGE 8 "RELEASE_DATE" "VERSION" +.UC +.SH "NAME" +mkelfImage \- make an elf network bootable image for linux +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBmkelfImage\fR [\-\-command\-line=\fIcommand line\fR] [\-\-kernel=\fIpath to vmlinux\fR] [\-\-ramdisk=\fIpath to ramdisk\fR] [\-\-output=\fIfile\fR] [\-\-ramdisk\-base=<start addr>] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +\&\fBmkelfImage\fR is a program that makes a elf boot image for linux kernel +images. The image should work with any i386 multiboot compliant boot loader, +an \s-1ELF\s0 bootloader that passes no options, a loader compliant with the linuxBIOS +elf booting spec or with the linux kexec kernel patch. A key feature +here is that nothing relies upon \s-1BIOS\s0 calls, but they are made when +necessary. This is useful for systems running linuxbios. +.SH "BUGS" +.IX Header "BUGS" +Not all kernel parameters can be passed with the multiboot image format. +ip configuration is not automatically passed to a node. +The ramdisk base is hard coded to 8MB by default. +This man page need to be updated. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +The kexec kernel patch. +LinuxBIOS. +Etherboot. +The multiboot standard. +.SH "COPYRIGHT" +.IX Header "COPYRIGHT" +mkelfImage is under the \s-1GNU\s0 Public License version 2 +.SH "AUTHOR" +.IX Header "AUTHOR" +Eric Biederman <ebiederman@lnxi.com> |