diff -urN kexec-tools-1.98/Makefile.main kexec-tools-1.98-ia64/Makefile.main --- kexec-tools-1.98/Makefile.main 2004-09-15 03:49:17.000000000 -0600 +++ kexec-tools-1.98-ia64/Makefile.main 2004-11-15 12:05:36.000000000 -0700 @@ -22,6 +22,7 @@ BINARIES_ppc:=$(SBINDIR)/kexec BINARIES_ppc64:=$(SBINDIR)/kexec BINARIES_x86_64:=$(SBINDIR)/kexec $(BINDIR)/kexec_test +BINARIES_ia64:=$(SBINDIR)/kexec BINARIES:=$(BINARIES_$(ARCH)) TARGETS:=$(BINARIES) $(MAN_PAGES) @@ -41,6 +42,12 @@ @echo ALPHA_AR=$(ALPHA_AR) @echo ALPHA_LD=$(ALPHA_LD) +install: + mkdir -p $(DESTDIR)/usr/sbin + install -m700 $(SBINDIR)/kexec $(DESTDIR)/usr/sbin + mkdir -p $(DESTDIR)/usr/share/man/man8 + install -m644 kexec/kexec.8 $(DESTDIR)/usr/share/man/man8 + clean: find $(OBJDIR) ! -name '*.d' -type f | xargs rm -f diff -urN kexec-tools-1.98/kexec/Makefile kexec-tools-1.98-ia64/kexec/Makefile --- kexec-tools-1.98/kexec/Makefile 2004-07-19 02:47:19.000000000 -0600 +++ kexec-tools-1.98-ia64/kexec/Makefile 2004-11-15 11:27:00.000000000 -0700 @@ -25,6 +25,10 @@ ifeq ($(ARCH),ppc64) KEXEC_C_SRCS+= kexec/kexec-zImage-ppc64.c endif +ifeq ($(ARCH),ia64) +KEXEC_C_SRCS+= kexec/kexec-ia64.c kexec/kexec-elf64-ia64.c +KEXEC_C_SRCS+= kexec/ifdown.c +endif KEXEC_C_OBJS:= $(patsubst %.c, $(OBJDIR)/%.o, $(KEXEC_C_SRCS)) KEXEC_C_DEPS:= $(patsubst %.c, $(OBJDIR)/%.d, $(KEXEC_C_SRCS)) diff -urN kexec-tools-1.98/kexec/kexec-elf64-ia64.c kexec-tools-1.98-ia64/kexec/kexec-elf64-ia64.c --- kexec-tools-1.98/kexec/kexec-elf64-ia64.c 1969-12-31 17:00:00.000000000 -0700 +++ kexec-tools-1.98-ia64/kexec/kexec-elf64-ia64.c 2004-11-15 11:27:00.000000000 -0700 @@ -0,0 +1,306 @@ +/* + * kexec: Linux boots Linux + * + * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com) + * Copyright (C) 2004 Albert Herranz + * Copyright (C) 2004 Silicon Graphics, Inc. + * Jesse Barnes + * Copyright (C) 2004 Khalid Aziz Hewlett Packard Co + * + * 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 (version 2 of the License). + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kexec.h" + +#define MAX_MEMORY_RANGES 64 +#define MAX_LINE 160 +static struct memory_range memory_range[MAX_MEMORY_RANGES]; + +static int debug = 0; + +#define BOOTLOADER "kexec" +#define BOOTLOADER_VERSION VERSION +#define MAX_COMMAND_LINE 256 + +/* + * elf64_ia64_probe - sanity check the elf image + * + * Make sure that the file image has a reasonable chance of working. + */ +int elf64_ia64_probe(FILE * file) +{ + Elf64_Ehdr ehdr; + if (fseek(file, 0, SEEK_SET) < 0) { + fprintf(stderr, "seek error: %s\n", strerror(errno)); + return -1; + } + if (fread(&ehdr, sizeof(ehdr), 1, file) != 1) { + if (debug) { + fprintf(stderr, "File too short.\n"); + } + return 0; + } + if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) { + /* No ELF header */ + if (debug) { + fprintf(stderr, "No ELF header.\n"); + } + return 0; + } + if (ehdr.e_ident[EI_CLASS] != ELFCLASS64) { + /* Not a 64bit ELF file */ + if (debug) { + fprintf(stderr, "Not a 64bit ELF file.\n"); + } + return 0; + } + if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) { + /* not a little endian ELF file */ + if (debug) { + fprintf(stderr, "Not a little endian ELF file.\n"); + } + return 0; + } + if ((ehdr.e_ident[EI_VERSION] != EV_CURRENT) || + (ehdr.e_version != EV_CURRENT)) { + /* unkown elf version */ + if (debug) { + fprintf(stderr, "Unknown ELF file version.\n"); + } + return 0; + } + if (ehdr.e_type != ET_EXEC) { + /* not an ELF executable */ + if (debug) { + fprintf(stderr, "Not an ELF executable.\n"); + } + return 0; + } + + if (ehdr.e_ehsize != sizeof(Elf64_Ehdr)) { + /* invalid ELF header size */ + if (debug) { + fprintf(stderr, "Invalid ELF header size.\n"); + } + return 0; + } + if (ehdr.e_phentsize != sizeof(Elf64_Phdr)) { + /* invalid program header size */ + if (debug) { + fprintf(stderr, "Invalid program header size.\n"); + } + return 0; + } + if ((ehdr.e_phoff == 0) || (ehdr.e_phnum == 0)) { + /* no program header */ + if (debug) { + fprintf(stderr, "No program header.\n"); + } + return 0; + } + /* Verify the architecuture specific bits */ + if (ehdr.e_machine != EM_IA_64) { + /* for a different architecture */ + if (debug) { + fprintf(stderr, "Not for this architecture.\n"); + } + return 0; + } + return 1; +} + +void elf64_ia64_usage(void) +{ + printf + ("-d, --debug Enable debugging to help spot a failure.\n" + " --command-line=STRING Set the kernel command line to STRING.\n" + " --append=STRING Set the kernel command line to STRING.\n"); +} + +int elf64_ia64_load(FILE * file, int argc, char **argv, + void **ret_entry, struct kexec_segment **ret_segments, + int *ret_nr_segments) +{ + Elf64_Ehdr ehdr; + Elf64_Phdr *phdr; + struct kexec_segment *segment; + int nr_segments; + size_t phdr_bytes; + const char *command_line; + int command_line_len; + unsigned long mstart; + char *buf; + size_t size; + int i; + int opt; +#define OPT_APPEND (OPT_MAX+0) + static const struct option options[] = { + KEXEC_OPTIONS + {"debug", 0, 0, OPT_DEBUG}, + {"command-line", 1, 0, OPT_APPEND}, + {"append", 1, 0, OPT_APPEND}, + {0, 0, 0, 0}, + }; + + static const char short_options[] = KEXEC_OPT_STR "d"; + + debug = 0; + command_line = 0; + while ((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) { + switch (opt) { + default: + /* Ignore core options */ + if (opt < OPT_MAX) { + break; + } + case '?': + usage(); + return -1; + case OPT_DEBUG: + debug = 1; + break; + case OPT_APPEND: + command_line = optarg; + break; + } + } + command_line_len = 0; + if (command_line) { + command_line_len = strlen(command_line) + 1; + } + + /* Read in the Elf header */ + if (fseek(file, 0, SEEK_SET) != 0) { + fprintf(stderr, "seek error: %s\n", strerror(errno)); + return -1; + } + if (fread(&ehdr, sizeof(ehdr), 1, file) != 1) { + fprintf(stderr, "read error: %s\n", strerror(errno)); + return -1; + } + /* do a sanity check on header */ + if (ehdr.e_ident[EI_MAG0] != 0x7f + || ehdr.e_ident[EI_MAG1] != 'E' + || ehdr.e_ident[EI_MAG2] != 'L' + || ehdr.e_ident[EI_MAG3] != 'F' + || ehdr.e_ident[EI_CLASS] != ELFCLASS64 + || ehdr.e_type != ET_EXEC + || ehdr.e_machine != EM_IA_64) { + fprintf(stderr, "Not an elf64 executable\n"); + return -1; + } + /* Read in the program header */ + phdr_bytes = sizeof(*phdr) * ehdr.e_phnum; + phdr = malloc(phdr_bytes); + if (phdr == 0) { + fprintf(stderr, "malloc failed: %s\n", strerror(errno)); + return -1; + } + if (fseek(file, ehdr.e_phoff, SEEK_SET) != 0) { + fprintf(stderr, "seek error: %s\n", strerror(errno)); + return -1; + } + if (fread(phdr, phdr_bytes, 1, file) != 1) { + fprintf(stderr, "read error: %s\n", strerror(errno)); + return -1; + } + + /* Setup the segments */ + segment = malloc(sizeof(*segment) * (ehdr.e_phnum + 1)); + if (segment == 0) { + fprintf(stderr, "malloc failed: %s\n", strerror(errno)); + return -1; + } + + /* Skip the argument segment */ + nr_segments = 0; + segment[nr_segments].buf = 0; + segment[nr_segments].bufsz = 0; + segment[nr_segments].mem = 0; + segment[nr_segments].memsz = 0; + nr_segments++; + + /* Now all the rest of the segments */ + for (i = 0; i < ehdr.e_phnum; i++) { + if (phdr[i].p_type != PT_LOAD) { + continue; + } + size = phdr[i].p_filesz; + if (size > phdr[i].p_memsz) { + size = phdr[i].p_memsz; + } + buf = malloc(size); + if (buf == 0) { + fprintf(stderr, "malloc failed: %s\n", strerror(errno)); + return -1; + } + segment[nr_segments].buf = buf; + segment[nr_segments].bufsz = size; + mstart = phdr[i].p_paddr; + segment[nr_segments].mem = (void *)mstart; + segment[nr_segments].memsz = phdr[i].p_memsz; + if (valid_memory_range(segment + nr_segments) < 0) { + fprintf(stderr, "Invalid memory segment %p - %p\n", + segment[nr_segments].mem, + ((char *)segment[nr_segments].mem) + + segment[nr_segments].memsz); + return -1; + } + nr_segments++; + if (size == 0) { + /* Don't do file I/O if there is nothing in the file */ + continue; + } + if (fseek(file, phdr[i].p_offset, SEEK_SET) != 0) { + fprintf(stderr, "seek failed: %s\n", strerror(errno)); + return -1; + } + if (fread(buf, size, 1, file) != 1) { + fprintf(stderr, "Read failed: %s\n", strerror(errno)); + return -1; + } + } + +#if 0 + /* Generate and setup the argument segment */ + if (sort_segments(segment, nr_segments) < 0) { + return -1; + } + + if (locate_arguments(segment, nr_segments, 4, ~0UL) < 0) { + return -1; + } + +#endif + *ret_entry = ehdr.e_entry; + *ret_nr_segments = nr_segments; + *ret_segments = segment; + return 0; +} diff -urN kexec-tools-1.98/kexec/kexec-ia64.c kexec-tools-1.98-ia64/kexec/kexec-ia64.c --- kexec-tools-1.98/kexec/kexec-ia64.c 1969-12-31 17:00:00.000000000 -0700 +++ kexec-tools-1.98-ia64/kexec/kexec-ia64.c 2004-11-15 11:27:00.000000000 -0700 @@ -0,0 +1,47 @@ +/* + * kexec: Linux boots Linux + * + * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com) + * Copyright (C) 2004 Albert Herranz + * Copyright (C) 2004 Silicon Graphics, Inc. + * Jesse Barnes + * + * 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 (version 2 of the License). + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include "kexec.h" +#include "kexec-ia64.h" + +#define MAX_MEMORY_RANGES 64 +#define MAX_LINE 160 +static struct memory_range memory_range[MAX_MEMORY_RANGES]; + +/* Return a sorted list of available memory ranges. */ +int get_memory_ranges(struct memory_range **range, int *ranges) +{ + return 0; +} + +/* Supported file types and callbacks */ +struct file_type file_type[] = { + {"elf64-ia64", elf64_ia64_probe, elf64_ia64_load, elf64_ia64_usage}, +}; +int file_types = sizeof(file_type) / sizeof(file_type[0]); + diff -urN kexec-tools-1.98/kexec/kexec-ia64.h kexec-tools-1.98-ia64/kexec/kexec-ia64.h --- kexec-tools-1.98/kexec/kexec-ia64.h 1969-12-31 17:00:00.000000000 -0700 +++ kexec-tools-1.98-ia64/kexec/kexec-ia64.h 2004-11-15 11:27:00.000000000 -0700 @@ -0,0 +1,9 @@ +#ifndef KEXEC_IA64_H +#define KEXEC_IA64_H + +int elf64_ia64_probe(FILE *file); +int elf64_ia64_load(FILE *file, int argc, char **argv, + void **ret_entry, struct kexec_segment **ret_segments, int *ret_nr_segments); +void elf64_ia64_usage(void); + +#endif /* KEXEC_IA64_H */ diff -urN kexec-tools-1.98/kexec/kexec.8 kexec-tools-1.98-ia64/kexec/kexec.8 --- kexec-tools-1.98/kexec/kexec.8 1969-12-31 17:00:00.000000000 -0700 +++ kexec-tools-1.98-ia64/kexec/kexec.8 2004-11-15 11:27:00.000000000 -0700 @@ -0,0 +1,45 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" First parameter, NAME, should be all caps +.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection +.\" other parameters are allowed: see man(7), man(1) +.TH KEXEC-TOOLS 8 "October 13, 2004" +.\" Please adjust this date whenever revising the manpage. +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +kexec-tools \- Tool to load a kernel for warm reboot and initiate a warm reboot +.SH SYNOPSIS +.B kexec-tools +.RI [ options ] " files" ... +.SH DESCRIPTION +.PP +.\" TeX users may be more comfortable with the \fB\fP and +.\" \fI\fP escape sequences to invode bold face and italics, +.\" respectively. +\fBkexec-tools\fP does not have a man page yet. Please use "kexec -h" for help. +.SH OPTIONS +These programs follow the usual GNU command line syntax, with long +options starting with two dashes (`-'). +A summary of options is included below. +For a complete description, see the Info files. +.TP +.B \-h, \-\-help +Show summary of options. +.TP +.B \-v, \-\-version +Show version of program. +.SH SEE ALSO +.SH AUTHOR +kexec-tools was written by Eric Biederman. +.PP +This manual page was written by Khalid Aziz , +for the Debian project (but may be used by others). diff -urN kexec-tools-1.98/kexec/kexec.c kexec-tools-1.98-ia64/kexec/kexec.c --- kexec-tools-1.98/kexec/kexec.c 2004-08-20 00:07:07.000000000 -0600 +++ kexec-tools-1.98-ia64/kexec/kexec.c 2004-11-15 12:54:22.134096799 -0700 @@ -35,6 +35,16 @@ { int i; +#ifdef __ia64__ + /* + * /proc/iomem on ia64 does not show where all memory is. If + * that is fixed up, we can make use of that to validate + * the memory range kernel will be loade din. Until then..... + * -- Khalid Aziz + */ + return 0; +#endif + for (i = 0; i < memory_ranges; i++) { unsigned long mstart, mend; unsigned long sstart, send;