1252 lines
37 KiB
Diff
1252 lines
37 KiB
Diff
diff -puN /dev/null kexec/arch/ia64/crashdump-ia64.c
|
|
--- /dev/null 2006-07-13 05:14:41.629277080 +0530
|
|
+++ kexec-tools-1.101-kdump-maneesh/kexec/arch/ia64/crashdump-ia64.c 2006-07-13 14:42:05.000000000 +0530
|
|
@@ -0,0 +1,351 @@
|
|
+/*
|
|
+ * kexec: crashdum support
|
|
+ * Copyright (C) 2005-2006 Zou Nan hai <nanhai.zou@intel.com> Intel Corp
|
|
+ *
|
|
+ * 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.
|
|
+ */
|
|
+#include <stdio.h>
|
|
+#include <string.h>
|
|
+#include <stdlib.h>
|
|
+#include <errno.h>
|
|
+#include <limits.h>
|
|
+#include <elf.h>
|
|
+#include "../../kexec.h"
|
|
+#include "../../kexec-elf.h"
|
|
+#include "../../kexec-syscall.h"
|
|
+#include "kexec-ia64.h"
|
|
+#include "crashdump-ia64.h"
|
|
+
|
|
+int memory_ranges = 0;
|
|
+#define LOAD_OFFSET (0xa000000000000000UL + 0x100000000UL - (1UL<<26))
|
|
+#define MAX_LINE 160
|
|
+/* Stores a sorted list of RAM memory ranges for which to create elf headers.
|
|
+ * A separate program header is created for backup region */
|
|
+static struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES];
|
|
+/* Memory region reserved for storing panic kernel and other data. */
|
|
+static struct memory_range crash_reserved_mem;
|
|
+unsigned long elfcorehdr;
|
|
+static unsigned long kernel_code_start;
|
|
+struct loaded_segment {
|
|
+ unsigned long start;
|
|
+ unsigned long end;
|
|
+ unsigned long reserved;
|
|
+};
|
|
+
|
|
+#define MAX_LOAD_SEGMENTS 128
|
|
+struct loaded_segment loaded_segments[MAX_LOAD_SEGMENTS];
|
|
+
|
|
+unsigned long loaded_segments_num, loaded_segments_base;
|
|
+static int seg_comp(const void *a, const void *b)
|
|
+{
|
|
+ const struct loaded_segment *x = a, *y = b;
|
|
+ /* avoid overflow */
|
|
+ if (x->start > y->start) return 1;
|
|
+ if (x->start < y->start) return -1;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/* purgatory code need this info to patch the EFI memmap
|
|
+ */
|
|
+static void add_loaded_segments_info(struct kexec_info *info,
|
|
+ struct mem_ehdr *ehdr, unsigned long max_addr)
|
|
+{
|
|
+ int i;
|
|
+ for(i = 0; i < ehdr->e_phnum; i++) {
|
|
+ unsigned long start, end;
|
|
+ struct mem_phdr *phdr;
|
|
+ phdr = &ehdr->e_phdr[i];
|
|
+ if (phdr->p_type != PT_LOAD)
|
|
+ continue;
|
|
+ start = phdr->p_paddr;
|
|
+ end = phdr->p_paddr + phdr->p_memsz;
|
|
+
|
|
+ loaded_segments[loaded_segments_num].start =
|
|
+ start&~(ELF_PAGE_SIZE-1);
|
|
+ loaded_segments[loaded_segments_num].end =
|
|
+ (end + ELF_PAGE_SIZE - 1)&~(ELF_PAGE_SIZE - 1);
|
|
+ loaded_segments[loaded_segments_num].reserved = 0;
|
|
+ loaded_segments_num++;
|
|
+ }
|
|
+}
|
|
+
|
|
+static int get_crash_notes_section_addr(unsigned long *addr, int cpu)
|
|
+{
|
|
+ char crash_notes[128];
|
|
+ char line[MAX_LINE];
|
|
+ FILE *fp;
|
|
+ sprintf(crash_notes, "/sys/devices/system/cpu/cpu%d/crash_notes", cpu);
|
|
+ fp = fopen(crash_notes, "r");
|
|
+ if (!fp) {
|
|
+ fprintf(stderr, "Cannot open %s: %s\n",
|
|
+ crash_notes, strerror(errno));
|
|
+ fprintf(stderr, "Try mounting sysfs\n");
|
|
+ return -1;
|
|
+ }
|
|
+ if (fscanf(fp, "%lx", addr) != 1) {
|
|
+ *addr = 0;
|
|
+ return -1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/* Removes crash reserve region from list of memory chunks for whom elf program
|
|
+ * headers have to be created. Assuming crash reserve region to be a single
|
|
+ * continuous area fully contained inside one of the memory chunks */
|
|
+static int exclude_crash_reserve_region(int *nr_ranges)
|
|
+{
|
|
+ int i, j, tidx = -1;
|
|
+ unsigned long cstart, cend;
|
|
+ struct memory_range temp_region;
|
|
+
|
|
+ /* Crash reserved region. */
|
|
+ cstart = crash_reserved_mem.start;
|
|
+ cend = crash_reserved_mem.end;
|
|
+
|
|
+ for (i = 0; i < (*nr_ranges); i++) {
|
|
+ unsigned long mstart, mend;
|
|
+ mstart = crash_memory_range[i].start;
|
|
+ mend = crash_memory_range[i].end;
|
|
+ if (cstart < mend && cend > mstart) {
|
|
+ if (cstart != mstart && cend != mend) {
|
|
+ /* Split memory region */
|
|
+ crash_memory_range[i].end = cstart - 1;
|
|
+ temp_region.start = cend + 1;
|
|
+ temp_region.end = mend;
|
|
+ temp_region.type = RANGE_RAM;
|
|
+ tidx = i+1;
|
|
+ } else if (cstart != mstart)
|
|
+ crash_memory_range[i].end = cstart - 1;
|
|
+ else
|
|
+ crash_memory_range[i].start = cend + 1;
|
|
+ }
|
|
+ }
|
|
+ /* Insert split memory region, if any. */
|
|
+ if (tidx >= 0) {
|
|
+ if (*nr_ranges == CRASH_MAX_MEMORY_RANGES) {
|
|
+ /* No space to insert another element. */
|
|
+ fprintf(stderr, "Error: Number of crash memory ranges"
|
|
+ " excedeed the max limit\n");
|
|
+ return -1;
|
|
+ }
|
|
+ for (j = (*nr_ranges - 1); j >= tidx; j--)
|
|
+ crash_memory_range[j+1] = crash_memory_range[j];
|
|
+ crash_memory_range[tidx].start = temp_region.start;
|
|
+ crash_memory_range[tidx].end = temp_region.end;
|
|
+ crash_memory_range[tidx].type = temp_region.type;
|
|
+ (*nr_ranges)++;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int prepare_crash_memory_elf64_headers(struct kexec_info *info,
|
|
+ void *buf, unsigned long size)
|
|
+{
|
|
+ Elf64_Ehdr *elf;
|
|
+ Elf64_Phdr *phdr;
|
|
+ int i;
|
|
+ long int nr_cpus = 0;
|
|
+ char *bufp = buf;
|
|
+ unsigned long notes_addr, notes_offset;
|
|
+
|
|
+ /* Setup ELF Header*/
|
|
+ elf = (Elf64_Ehdr *) bufp;
|
|
+ bufp += sizeof(Elf64_Ehdr);
|
|
+ memcpy(elf->e_ident, ELFMAG, SELFMAG);
|
|
+ elf->e_ident[EI_CLASS] = ELFCLASS64;
|
|
+ elf->e_ident[EI_DATA] = ELFDATA2LSB;
|
|
+ elf->e_ident[EI_VERSION]= EV_CURRENT;
|
|
+ elf->e_ident[EI_OSABI] = ELFOSABI_NONE;
|
|
+ memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
|
|
+ elf->e_type = ET_CORE;
|
|
+ elf->e_machine = EM_IA_64;
|
|
+ elf->e_version = EV_CURRENT;
|
|
+ elf->e_entry = 0;
|
|
+ elf->e_phoff = sizeof(Elf64_Ehdr);
|
|
+ elf->e_shoff = 0;
|
|
+ elf->e_flags = 0;
|
|
+ elf->e_ehsize = sizeof(Elf64_Ehdr);
|
|
+ elf->e_phentsize= sizeof(Elf64_Phdr);
|
|
+ elf->e_phnum = 0;
|
|
+ elf->e_shentsize= 0;
|
|
+ elf->e_shnum = 0;
|
|
+ elf->e_shstrndx = 0;
|
|
+
|
|
+ /* PT_NOTE program headers. One per cpu*/
|
|
+ nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
|
|
+ if (nr_cpus < 0) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ /* Need to find a better way to determine per cpu notes section size. */
|
|
+#define MAX_NOTE_BYTES 1024
|
|
+
|
|
+ for (i = 0; i < nr_cpus; i++) {
|
|
+ if (get_crash_notes_section_addr (¬es_addr, i) < 0)
|
|
+ break;
|
|
+ notes_offset = notes_addr;
|
|
+ phdr = (Elf64_Phdr *) bufp;
|
|
+ bufp += sizeof(Elf64_Phdr);
|
|
+ phdr->p_type = PT_NOTE;
|
|
+ phdr->p_flags = 0;
|
|
+ phdr->p_offset = notes_offset;
|
|
+ phdr->p_vaddr = phdr->p_paddr = notes_offset;
|
|
+ phdr->p_filesz = phdr->p_memsz = MAX_NOTE_BYTES;
|
|
+ /* Do we need any alignment of segments? */
|
|
+ phdr->p_align = 0;
|
|
+
|
|
+ /* Increment number of program headers. */
|
|
+ (elf->e_phnum)++;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < memory_ranges; i++) {
|
|
+ unsigned long mstart, mend;
|
|
+ mstart = crash_memory_range[i].start;
|
|
+ mend = crash_memory_range[i].end;
|
|
+ if (!mstart && !mend)
|
|
+ break;
|
|
+ phdr = (Elf64_Phdr *) bufp;
|
|
+ bufp += sizeof(Elf64_Phdr);
|
|
+ phdr->p_type = PT_LOAD;
|
|
+ phdr->p_flags = PF_R|PF_W|PF_X;
|
|
+ phdr->p_offset = mstart;
|
|
+ /*add region 5 mapping for kernel*/
|
|
+ if (kernel_code_start >= mstart && kernel_code_start < mend) {
|
|
+ phdr->p_vaddr = mstart + LOAD_OFFSET;
|
|
+ phdr->p_paddr = mstart;
|
|
+ phdr->p_filesz = phdr->p_memsz = mend - mstart + 1;
|
|
+ phdr->p_align = 0;
|
|
+ (elf->e_phnum)++;
|
|
+
|
|
+ phdr = (Elf64_Phdr *) bufp;
|
|
+ bufp += sizeof(Elf64_Phdr);
|
|
+ phdr->p_type = PT_LOAD;
|
|
+ phdr->p_flags = PF_R|PF_W|PF_X;
|
|
+ phdr->p_offset = mstart;
|
|
+ }
|
|
+ phdr->p_vaddr = mstart + PAGE_OFFSET;
|
|
+ phdr->p_paddr = mstart;
|
|
+ phdr->p_filesz = phdr->p_memsz = mend - mstart + 1;
|
|
+ phdr->p_align = 0;
|
|
+ (elf->e_phnum)++;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
|
|
+{
|
|
+ const char iomem[]= "/proc/iomem";
|
|
+ char line[MAX_LINE];
|
|
+ FILE *fp;
|
|
+ unsigned long start, end;
|
|
+
|
|
+ fp = fopen(iomem, "r");
|
|
+ if (!fp) {
|
|
+ fprintf(stderr, "Cannot open %s: %s\n",
|
|
+ iomem, strerror(errno));
|
|
+ return -1;
|
|
+ }
|
|
+ while(fgets(line, sizeof(line), fp) != 0) {
|
|
+ char *str;
|
|
+ int type, consumed, count;
|
|
+ if (memory_ranges >= CRASH_MAX_MEMORY_RANGES)
|
|
+ break;
|
|
+ count = sscanf(line, "%lx-%lx : %n",
|
|
+ &start, &end, &consumed);
|
|
+ str = line + consumed;
|
|
+ if (count != 2)
|
|
+ continue;
|
|
+
|
|
+ if (memcmp(str, "System RAM\n", 11) == 0) {
|
|
+ type = RANGE_RAM;
|
|
+ } else if (memcmp(str, "Crash kernel\n", 13) == 0) {
|
|
+ /* Reserved memory region. New kernel can
|
|
+ * use this region to boot into. */
|
|
+ crash_reserved_mem.start = start;
|
|
+ crash_reserved_mem.end = end;
|
|
+ crash_reserved_mem.type = RANGE_RAM;
|
|
+ continue;
|
|
+ }
|
|
+ else if (memcmp(str, "Kernel code\n", 12) == 0) {
|
|
+ kernel_code_start = start;
|
|
+ continue;
|
|
+ }else
|
|
+ continue;
|
|
+ crash_memory_range[memory_ranges].start = start;
|
|
+ crash_memory_range[memory_ranges].end = end;
|
|
+ crash_memory_range[memory_ranges].type = type;
|
|
+ memory_ranges++;
|
|
+ }
|
|
+ fclose(fp);
|
|
+ if (exclude_crash_reserve_region(&memory_ranges) < 0)
|
|
+ return -1;
|
|
+ *ranges = memory_ranges;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void
|
|
+cmdline_add_elfcorehdr(char **cmdline, unsigned long addr)
|
|
+{
|
|
+ char *str = *cmdline;
|
|
+ char buf[64];
|
|
+ size_t len;
|
|
+ sprintf(buf, " elfcorehdr=%ldK", addr/1024);
|
|
+ len = strlen(str) + strlen(buf) + 1;
|
|
+ str = xmalloc(len);
|
|
+ sprintf(str, "%s%s", *cmdline, buf);
|
|
+ *cmdline = str;
|
|
+}
|
|
+
|
|
+int load_crashdump_segments(struct kexec_info *info, struct mem_ehdr *ehdr,
|
|
+ unsigned long max_addr, unsigned long min_base,
|
|
+ char **cmdline)
|
|
+{
|
|
+ //struct memory_range *mem_range, *memmap_p;
|
|
+ struct memory_range *mem_range;
|
|
+ int nr_ranges;
|
|
+ size_t size;
|
|
+ void *tmp;
|
|
+ if (info->kexec_flags & KEXEC_ON_CRASH ) {
|
|
+ if (get_crash_memory_ranges(&mem_range, &nr_ranges) == 0) {
|
|
+ size = sizeof(Elf64_Ehdr) +
|
|
+ (nr_ranges + 1) * sizeof(Elf64_Phdr);
|
|
+ size = (size + EFI_PAGE_SIZE - 1) & ~(EFI_PAGE_SIZE - 1);
|
|
+ tmp = xmalloc(size);
|
|
+ memset(tmp, 0, size);
|
|
+ if (prepare_crash_memory_elf64_headers(info, tmp, size) < 0)
|
|
+ return -1;
|
|
+ elfcorehdr = add_buffer(info, tmp, size, size, EFI_PAGE_SIZE, min_base,
|
|
+ max_addr, -1);
|
|
+ loaded_segments[loaded_segments_num].start = elfcorehdr;
|
|
+ loaded_segments[loaded_segments_num].end = elfcorehdr + size;
|
|
+ loaded_segments[loaded_segments_num].reserved = 1;
|
|
+ loaded_segments_num++;
|
|
+ cmdline_add_elfcorehdr(cmdline, elfcorehdr);
|
|
+ }
|
|
+ }
|
|
+ add_loaded_segments_info(info, ehdr, max_addr);
|
|
+ size = sizeof(struct loaded_segment) * loaded_segments_num;
|
|
+ qsort(loaded_segments, loaded_segments_num,
|
|
+ sizeof(struct loaded_segment), seg_comp);
|
|
+ loaded_segments_base = add_buffer(info, loaded_segments,
|
|
+ size, size, 16, 0, max_addr, -1);
|
|
+
|
|
+ elf_rel_set_symbol(&info->rhdr, "__loaded_segments",
|
|
+ &loaded_segments_base, sizeof(long));
|
|
+ elf_rel_set_symbol(&info->rhdr, "__loaded_segments_num",
|
|
+ &loaded_segments_num, sizeof(long));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
diff -puN /dev/null kexec/arch/ia64/crashdump-ia64.h
|
|
--- /dev/null 2006-07-13 05:14:41.629277080 +0530
|
|
+++ kexec-tools-1.101-kdump-maneesh/kexec/arch/ia64/crashdump-ia64.h 2006-07-13 14:42:05.000000000 +0530
|
|
@@ -0,0 +1,13 @@
|
|
+#ifndef CRASHDUMP_IA64_H
|
|
+#define CRASHDUMP_IA64_H
|
|
+
|
|
+#define PAGE_OFFSET 0xe000000000000000UL
|
|
+#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
|
|
+extern int load_crashdump_segments(struct kexec_info *info,
|
|
+ struct mem_ehdr *ehdr, unsigned long max_addr,
|
|
+ unsigned long min_base, char **cmdline);
|
|
+
|
|
+#define CRASH_MAX_MEMMAP_NR (KEXEC_MAX_SEGMENTS + 1)
|
|
+#define CRASH_MAX_MEMORY_RANGES (MAX_MEMORY_RANGES + 2)
|
|
+
|
|
+#endif
|
|
diff -puN kexec/arch/ia64/kexec-elf-ia64.c~kdump-ia64 kexec/arch/ia64/kexec-elf-ia64.c
|
|
--- kexec-tools-1.101-kdump/kexec/arch/ia64/kexec-elf-ia64.c~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
|
|
+++ kexec-tools-1.101-kdump-maneesh/kexec/arch/ia64/kexec-elf-ia64.c 2006-07-13 14:42:05.000000000 +0530
|
|
@@ -40,7 +40,9 @@
|
|
#include <boot/elf_boot.h>
|
|
#include <ip_checksum.h>
|
|
#include "../../kexec.h"
|
|
+#include "../../kexec-syscall.h"
|
|
#include "../../kexec-elf.h"
|
|
+#include "crashdump-ia64.h"
|
|
#include <arch/options.h>
|
|
|
|
static const int probe_debug = 0;
|
|
@@ -80,6 +82,28 @@ void elf_ia64_usage(void)
|
|
" --initrd=FILE Use FILE as the kernel's initial ramdisk.\n");
|
|
}
|
|
|
|
+/* Move the crash kerenl physical offset to reserved region
|
|
+ */
|
|
+static void move_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr)
|
|
+{
|
|
+ int i;
|
|
+ long offset;
|
|
+ struct mem_phdr *phdr;
|
|
+ for(i = 0; i < ehdr->e_phnum; i++) {
|
|
+ phdr = &ehdr->e_phdr[i];
|
|
+ if (phdr->p_type == PT_LOAD) {
|
|
+ offset = mem_min - phdr->p_paddr;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ ehdr->e_entry += offset;
|
|
+ for(i = 0; i < ehdr->e_phnum; i++) {
|
|
+ phdr = &ehdr->e_phdr[i];
|
|
+ if (phdr->p_type == PT_LOAD)
|
|
+ phdr->p_paddr += offset;
|
|
+ }
|
|
+}
|
|
+
|
|
int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
|
|
struct kexec_info *info)
|
|
{
|
|
@@ -89,9 +113,11 @@ int elf_ia64_load(int argc, char **argv,
|
|
off_t ramdisk_size = 0;
|
|
unsigned long command_line_len;
|
|
unsigned long entry, max_addr, gp_value;
|
|
- unsigned command_line_base, ramdisk_base;
|
|
+ unsigned long command_line_base, ramdisk_base;
|
|
+ unsigned long efi_memmap_base, efi_memmap_size;
|
|
int result;
|
|
int opt;
|
|
+ char *efi_memmap_buf;
|
|
#define OPT_APPEND (OPT_ARCH_MAX+0)
|
|
#define OPT_RAMDISK (OPT_ARCH_MAX+1)
|
|
static const struct option options[] = {
|
|
@@ -135,6 +161,15 @@ int elf_ia64_load(int argc, char **argv,
|
|
free_elf_info(&ehdr);
|
|
return result;
|
|
}
|
|
+
|
|
+ if (info->kexec_flags & KEXEC_ON_CRASH ) {
|
|
+ if ((mem_min == 0x00) && (mem_max = ULONG_MAX)) {
|
|
+ fprintf(stderr, "Failed to find crash kernel region in /proc/iomem\n");
|
|
+ return -1;
|
|
+ }
|
|
+ move_loaded_segments(info, &ehdr);
|
|
+ }
|
|
+
|
|
entry = ehdr.e_entry;
|
|
max_addr = elf_max_addr(&ehdr);
|
|
|
|
@@ -149,17 +184,48 @@ int elf_ia64_load(int argc, char **argv,
|
|
|
|
/* Load the setup code */
|
|
elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
|
|
- 0x80000, ULONG_MAX, 1);
|
|
+ 0x0, ULONG_MAX, -1);
|
|
|
|
- if (command_line_len) {
|
|
+
|
|
+ if (load_crashdump_segments(info, &ehdr, max_addr, 0,
|
|
+ &command_line) < 0)
|
|
+ return -1;
|
|
+
|
|
+ // reserve 8k for efi_memmap
|
|
+ efi_memmap_size = 1UL<<14;
|
|
+ efi_memmap_buf = xmalloc(efi_memmap_size);
|
|
+ efi_memmap_base = add_buffer(info, efi_memmap_buf,
|
|
+ efi_memmap_size, efi_memmap_size, 4096, 0,
|
|
+ max_addr, -1);
|
|
+
|
|
+ elf_rel_set_symbol(&info->rhdr, "__efi_memmap_base",
|
|
+ &efi_memmap_base, sizeof(long));
|
|
+
|
|
+ elf_rel_set_symbol(&info->rhdr, "__efi_memmap_size",
|
|
+ &efi_memmap_size, sizeof(long));
|
|
+ if (command_line) {
|
|
+ command_line_len = strlen(command_line) + 1;
|
|
+ }
|
|
+ if (command_line_len || (info->kexec_flags & KEXEC_ON_CRASH )) {
|
|
char *cmdline = xmalloc(command_line_len);
|
|
strcpy(cmdline, command_line);
|
|
+
|
|
+ if (info->kexec_flags & KEXEC_ON_CRASH) {
|
|
+ char buf[128];
|
|
+ sprintf(buf," max_addr=%lluM min_addr=%lluM",
|
|
+ mem_max>>20, mem_min>>20);
|
|
+ command_line_len = strlen(cmdline) + strlen(buf) + 1;
|
|
+ cmdline = xrealloc(cmdline, command_line_len);
|
|
+ strcat(cmdline, buf);
|
|
+ }
|
|
+
|
|
command_line_len = (command_line_len + 15)&(~15);
|
|
+ command_line_base = add_buffer(info, cmdline,
|
|
+ command_line_len, command_line_len,
|
|
+ getpagesize(), 0UL,
|
|
+ max_addr, -1);
|
|
elf_rel_set_symbol(&info->rhdr, "__command_line_len",
|
|
&command_line_len, sizeof(long));
|
|
- command_line_base = add_buffer(info, cmdline,
|
|
- command_line_len, command_line_len,
|
|
- 16, 0, max_addr, 1);
|
|
elf_rel_set_symbol(&info->rhdr, "__command_line",
|
|
&command_line_base, sizeof(long));
|
|
}
|
|
@@ -168,7 +234,7 @@ int elf_ia64_load(int argc, char **argv,
|
|
ramdisk_buf = slurp_file(ramdisk, &ramdisk_size);
|
|
ramdisk_base = add_buffer(info, ramdisk_buf, ramdisk_size,
|
|
ramdisk_size,
|
|
- getpagesize(), 0, max_addr, 1);
|
|
+ getpagesize(), 0, max_addr, -1);
|
|
elf_rel_set_symbol(&info->rhdr, "__ramdisk_base",
|
|
&ramdisk_base, sizeof(long));
|
|
elf_rel_set_symbol(&info->rhdr, "__ramdisk_size",
|
|
diff -puN kexec/arch/ia64/kexec-elf-rel-ia64.c~kdump-ia64 kexec/arch/ia64/kexec-elf-rel-ia64.c
|
|
--- kexec-tools-1.101-kdump/kexec/arch/ia64/kexec-elf-rel-ia64.c~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
|
|
+++ kexec-tools-1.101-kdump-maneesh/kexec/arch/ia64/kexec-elf-rel-ia64.c 2006-07-13 14:42:05.000000000 +0530
|
|
@@ -1,3 +1,26 @@
|
|
+/*
|
|
+ * Copyright (C) 2005-2006 Zou Nan hai (nanhai.zou@intel.com)
|
|
+ *
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+/* pugatory relocation code
|
|
+ * Most of the code in this file is
|
|
+ * based on arch/ia64/kernel/module.c in Linux kernel
|
|
+ */
|
|
+
|
|
+
|
|
/* Most of the code in this file is
|
|
* based on arch/ia64/kernel/module.c in Linux kernel
|
|
*/
|
|
@@ -43,6 +66,15 @@ ia64_patch (uint64_t insn_addr, uint64_t
|
|
b[1] = (b1 & ~m1) | (v1 & m1);
|
|
}
|
|
|
|
+static void
|
|
+put_unaligned64(unsigned long val, unsigned char *location)
|
|
+{
|
|
+ unsigned char *src = (unsigned char *)&val;
|
|
+ int i;
|
|
+ for (i = 0; i < sizeof(long); i++)
|
|
+ *location++ = *src++;
|
|
+}
|
|
+
|
|
static inline uint64_t
|
|
bundle (const uint64_t insn)
|
|
{
|
|
@@ -102,6 +134,11 @@ void machine_apply_elf_rel(struct mem_eh
|
|
| ((value & 0x0fffffUL) << 13) /* bit 0 -> 13 */));
|
|
}
|
|
break;
|
|
+ case R_IA64_PCREL64LSB: {
|
|
+ value = value - address;
|
|
+ put_unaligned64(value, location);
|
|
+ } break;
|
|
+ case R_IA64_GPREL22:
|
|
case R_IA64_LTOFF22X:
|
|
if (value - gp_value + MAX_LTOFF/2 >= MAX_LTOFF)
|
|
die("value out of gp relative range");
|
|
diff -puN kexec/arch/ia64/kexec-ia64.h~kdump-ia64 kexec/arch/ia64/kexec-ia64.h
|
|
--- kexec-tools-1.101-kdump/kexec/arch/ia64/kexec-ia64.h~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
|
|
+++ kexec-tools-1.101-kdump-maneesh/kexec/arch/ia64/kexec-ia64.h 2006-07-13 14:42:05.000000000 +0530
|
|
@@ -7,5 +7,7 @@ int elf_ia64_probe(const char *buf, off_
|
|
int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
|
|
struct kexec_info *info);
|
|
void elf_ia64_usage(void);
|
|
-
|
|
+#define MAX_MEMORY_RANGES 1024
|
|
+#define EFI_PAGE_SIZE (1UL<<12)
|
|
+#define ELF_PAGE_SIZE (1UL<<16)
|
|
#endif /* KEXEC_IA64_H */
|
|
diff -puN kexec/arch/ia64/Makefile~kdump-ia64 kexec/arch/ia64/Makefile
|
|
--- kexec-tools-1.101-kdump/kexec/arch/ia64/Makefile~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
|
|
+++ kexec-tools-1.101-kdump-maneesh/kexec/arch/ia64/Makefile 2006-07-13 14:42:05.000000000 +0530
|
|
@@ -4,3 +4,5 @@
|
|
KEXEC_C_SRCS+= kexec/arch/ia64/kexec-ia64.c
|
|
KEXEC_C_SRCS+= kexec/arch/ia64/kexec-elf-ia64.c
|
|
KEXEC_C_SRCS+= kexec/arch/ia64/kexec-elf-rel-ia64.c
|
|
+KEXEC_C_SRCS+= kexec/arch/ia64/crashdump-ia64.c
|
|
+
|
|
diff -puN kexec/kexec.c~kdump-ia64 kexec/kexec.c
|
|
--- kexec-tools-1.101-kdump/kexec/kexec.c~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
|
|
+++ kexec-tools-1.101-kdump-maneesh/kexec/kexec.c 2006-07-13 14:42:05.000000000 +0530
|
|
@@ -96,6 +96,9 @@ int valid_memory_range(unsigned long sst
|
|
continue;
|
|
mstart = memory_range[i].start;
|
|
mend = memory_range[i].end;
|
|
+ if (i < memory_ranges - 1 && mend == memory_range[i+1].start)
|
|
+ mend = memory_range[i+1].end;
|
|
+
|
|
/* Check to see if we are fully contained */
|
|
if ((mstart <= sstart) && (mend >= send)) {
|
|
return 1;
|
|
diff -puN kexec/kexec-sha256.h~kdump-ia64 kexec/kexec-sha256.h
|
|
--- kexec-tools-1.101-kdump/kexec/kexec-sha256.h~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
|
|
+++ kexec-tools-1.101-kdump-maneesh/kexec/kexec-sha256.h 2006-07-13 14:42:05.000000000 +0530
|
|
@@ -6,6 +6,6 @@ struct sha256_region {
|
|
unsigned long len;
|
|
};
|
|
|
|
-#define SHA256_REGIONS 8
|
|
+#define SHA256_REGIONS 16
|
|
|
|
#endif /* KEXEC_SHA256_H */
|
|
diff -puN purgatory/arch/ia64/console-ia64.c~kdump-ia64 purgatory/arch/ia64/console-ia64.c
|
|
--- kexec-tools-1.101-kdump/purgatory/arch/ia64/console-ia64.c~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
|
|
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/console-ia64.c 2006-07-13 14:42:05.000000000 +0530
|
|
@@ -1,5 +1,47 @@
|
|
#include <purgatory.h>
|
|
+#include "io.h"
|
|
+
|
|
+#define VGABASE UNCACHED(0xb8000)
|
|
+
|
|
+/* code based on i386 console code
|
|
+ * TODO add serial support
|
|
+ */
|
|
+#define MAX_YPOS 25
|
|
+#define MAX_XPOS 80
|
|
+
|
|
+unsigned long current_ypos = 1, current_xpos = 0;
|
|
+
|
|
+static void putchar_vga(int ch)
|
|
+{
|
|
+ int i, k, j;
|
|
+
|
|
+ if (current_ypos >= MAX_YPOS) {
|
|
+ /* scroll 1 line up */
|
|
+ for (k = 1, j = 0; k < MAX_YPOS; k++, j++) {
|
|
+ for (i = 0; i < MAX_XPOS; i++) {
|
|
+ writew(readw(VGABASE + 2*(MAX_XPOS*k + i)),
|
|
+ VGABASE + 2*(MAX_XPOS*j + i));
|
|
+ }
|
|
+ }
|
|
+ for (i = 0; i < MAX_XPOS; i++)
|
|
+ writew(0x720, VGABASE + 2*(MAX_XPOS*j + i));
|
|
+ current_ypos = MAX_YPOS-1;
|
|
+ }
|
|
+ if (ch == '\n') {
|
|
+ current_xpos = 0;
|
|
+ current_ypos++;
|
|
+ } else if (ch != '\r') {
|
|
+ writew(((0x7 << 8) | (unsigned short) ch),
|
|
+ VGABASE + 2*(MAX_XPOS*current_ypos +
|
|
+ current_xpos++));
|
|
+ if (current_xpos >= MAX_XPOS) {
|
|
+ current_xpos = 0;
|
|
+ current_ypos++;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
void putchar(int ch)
|
|
{
|
|
- /* Nothing for now */
|
|
+ putchar_vga(ch);
|
|
}
|
|
diff -puN purgatory/arch/ia64/entry.S~kdump-ia64 purgatory/arch/ia64/entry.S
|
|
--- kexec-tools-1.101-kdump/purgatory/arch/ia64/entry.S~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
|
|
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/entry.S 2006-07-13 14:42:05.000000000 +0530
|
|
@@ -1,7 +1,7 @@
|
|
/*
|
|
* purgatory: setup code
|
|
*
|
|
- * Copyright (C) 2005 Zou Nan hai (nanhai.zou@intel.com)
|
|
+ * Copyright (C) 2005-2006 Zou Nan hai (nanhai.zou@intel.com)
|
|
*
|
|
* 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
|
|
@@ -16,6 +16,10 @@
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
+#define DECLARE_DATA8(name) \
|
|
+.global name; \
|
|
+.size name, 8; \
|
|
+name: data8 0x0
|
|
|
|
.global __dummy_efi_function
|
|
.align 32
|
|
@@ -35,18 +39,10 @@ purgatory_start:
|
|
ld8 gp=[r2];;
|
|
br.call.sptk.many b0=purgatory
|
|
;;
|
|
- alloc r2 = ar.pfs, 0, 0, 5, 0
|
|
+ alloc r2 = ar.pfs, 0, 0, 2, 0
|
|
;;
|
|
mov out0=r28
|
|
-
|
|
- movl r2=__command_line;;
|
|
- ld8 out1=[r2];;
|
|
- movl r2=__command_line_len;;
|
|
- ld8 out2=[r2];;
|
|
- movl r2=__ramdisk_base;;
|
|
- ld8 out3=[r2];;
|
|
- movl r2=__ramdisk_size;;
|
|
- ld8 out4=[r2];;
|
|
+ movl out1=__ramdisk_base;;
|
|
br.call.sptk.many b0=ia64_env_setup
|
|
movl r10=__kernel_entry;;
|
|
ld8 r14=[r10];;
|
|
@@ -58,28 +54,14 @@ purgatory_start:
|
|
br.call.sptk.many b0=b6
|
|
.endp purgatory_start
|
|
|
|
-.align 32
|
|
-.global __kernel_entry
|
|
-.size __kernel_entry, 8
|
|
-__kernel_entry:
|
|
- data8 0x0
|
|
-.global __command_line
|
|
-.size __command_line, 8
|
|
-__command_line:
|
|
- data8 0x0
|
|
-.global __command_line_len
|
|
-.size __command_line_len, 8
|
|
-__command_line_len:
|
|
- data8 0x0
|
|
-.global __ramdisk_base
|
|
-.size __ramdisk_base, 8
|
|
-__ramdisk_base:
|
|
- data8 0x0
|
|
-.global __ramdisk_size
|
|
-.size __ramdisk_size, 8
|
|
-__ramdisk_size:
|
|
- data8 0x0
|
|
-.global __gp_value
|
|
-.size __gp_value, 8
|
|
-__gp_value:
|
|
- data8 0x0
|
|
+DECLARE_DATA8(__kernel_entry)
|
|
+DECLARE_DATA8(__ramdisk_base)
|
|
+DECLARE_DATA8(__ramdisk_size)
|
|
+DECLARE_DATA8(__command_line)
|
|
+DECLARE_DATA8(__command_line_len)
|
|
+DECLARE_DATA8(__efi_memmap_base)
|
|
+DECLARE_DATA8(__efi_memmap_size)
|
|
+DECLARE_DATA8(__loaded_segments)
|
|
+DECLARE_DATA8(__loaded_segments_num)
|
|
+
|
|
+DECLARE_DATA8(__gp_value)
|
|
diff -puN /dev/null purgatory/arch/ia64/io.h
|
|
--- /dev/null 2006-07-13 05:14:41.629277080 +0530
|
|
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/io.h 2006-07-13 14:42:05.000000000 +0530
|
|
@@ -0,0 +1,94 @@
|
|
+#ifndef IO_H
|
|
+#define IO_H
|
|
+#define UNCACHED(x) (void *)((x)|(1UL<<63))
|
|
+#define MF() asm volatile ("mf.a" ::: "memory")
|
|
+#define IO_SPACE_ENCODING(p) ((((p) >> 2) << 12) | (p & 0xfff))
|
|
+
|
|
+static inline void *io_addr (unsigned long port)
|
|
+{
|
|
+ unsigned long offset;
|
|
+ unsigned long io_base;
|
|
+ asm volatile ("mov %0=ar.k0":"=r"(io_base));
|
|
+ offset = IO_SPACE_ENCODING(port);
|
|
+ return UNCACHED(io_base | offset);
|
|
+}
|
|
+
|
|
+static inline unsigned int inb (unsigned long port)
|
|
+{
|
|
+ volatile unsigned char *addr = io_addr(port);
|
|
+ unsigned char ret;
|
|
+ ret = *addr;
|
|
+ MF();
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static inline unsigned int inw (unsigned long port)
|
|
+{
|
|
+ volatile unsigned short *addr = io_addr(port);
|
|
+ unsigned short ret;
|
|
+
|
|
+ ret = *addr;
|
|
+ MF();
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static inline unsigned int ia64_inl (unsigned long port)
|
|
+{
|
|
+ volatile unsigned int *addr = __ia64_mk_io_addr(port);
|
|
+ unsigned int ret;
|
|
+ ret = *addr;
|
|
+ MF();
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static inline void outb (unsigned char val, unsigned long port)
|
|
+{
|
|
+ volatile unsigned char *addr = io_addr(port);
|
|
+
|
|
+ *addr = val;
|
|
+ MF();
|
|
+}
|
|
+
|
|
+static inline void outw (unsigned short val, unsigned long port)
|
|
+{
|
|
+ volatile unsigned short *addr = io_addr(port);
|
|
+
|
|
+ *addr = val;
|
|
+ MF();
|
|
+}
|
|
+
|
|
+static inline void outl (unsigned int val, unsigned long port)
|
|
+{
|
|
+ volatile unsigned int *addr = io_addr(port);
|
|
+
|
|
+ *addr = val;
|
|
+ MF();
|
|
+}
|
|
+
|
|
+
|
|
+static inline unsigned char readb(const volatile void *addr)
|
|
+{
|
|
+ return *(volatile unsigned char *) addr;
|
|
+}
|
|
+static inline unsigned short readw(const volatile void *addr)
|
|
+{
|
|
+ return *(volatile unsigned short *) addr;
|
|
+}
|
|
+static inline unsigned int readl(const volatile void *addr)
|
|
+{
|
|
+ return *(volatile unsigned int *) addr;
|
|
+}
|
|
+
|
|
+static inline void writeb(unsigned char b, volatile void *addr)
|
|
+{
|
|
+ *(volatile unsigned char *) addr = b;
|
|
+}
|
|
+static inline void writew(unsigned short b, volatile void *addr)
|
|
+{
|
|
+ *(volatile unsigned short *) addr = b;
|
|
+}
|
|
+static inline void writel(unsigned int b, volatile void *addr)
|
|
+{
|
|
+ *(volatile unsigned int *) addr = b;
|
|
+}
|
|
+#endif
|
|
diff -puN purgatory/arch/ia64/Makefile~kdump-ia64 purgatory/arch/ia64/Makefile
|
|
--- kexec-tools-1.101-kdump/purgatory/arch/ia64/Makefile~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
|
|
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/Makefile 2006-07-13 14:42:05.000000000 +0530
|
|
@@ -5,5 +5,5 @@ PCFLAGS += -ffixed-r28
|
|
PURGATORY_S_SRCS+= purgatory/arch/ia64/entry.S
|
|
PURGATORY_C_SRCS+= purgatory/arch/ia64/purgatory-ia64.c
|
|
PURGATORY_C_SRCS+= purgatory/arch/ia64/console-ia64.c
|
|
-PURGATORY_C_SRCS+=
|
|
+PURGATORY_C_SRCS+= purgatory/arch/ia64/vga.c
|
|
|
|
diff -puN purgatory/arch/ia64/purgatory-ia64.c~kdump-ia64 purgatory/arch/ia64/purgatory-ia64.c
|
|
--- kexec-tools-1.101-kdump/purgatory/arch/ia64/purgatory-ia64.c~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
|
|
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/purgatory-ia64.c 2006-07-13 14:42:05.000000000 +0530
|
|
@@ -1,9 +1,47 @@
|
|
+/*
|
|
+ * purgatory: setup code
|
|
+ *
|
|
+ * Copyright (C) 2005-2006 Zou Nan hai (nanhai.zou@intel.com)
|
|
+ *
|
|
+ * 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.
|
|
+ */
|
|
#include <purgatory.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include "purgatory-ia64.h"
|
|
|
|
-#define PAGE_OFFSET 0xe000000000000000
|
|
+#define PAGE_OFFSET 0xe000000000000000UL
|
|
+
|
|
+#define EFI_PAGE_SHIFT 12
|
|
+#define EFI_PAGE_SIZE (1UL<<EFI_PAGE_SHIFT)
|
|
+#define EFI_PAGE_ALIGN(x) ((x + EFI_PAGE_SIZE - 1)&~(EFI_PAGE_SIZE-1))
|
|
+/* Memory types: */
|
|
+#define EFI_RESERVED_TYPE 0
|
|
+#define EFI_LOADER_CODE 1
|
|
+#define EFI_LOADER_DATA 2
|
|
+#define EFI_BOOT_SERVICES_CODE 3
|
|
+#define EFI_BOOT_SERVICES_DATA 4
|
|
+#define EFI_RUNTIME_SERVICES_CODE 5
|
|
+#define EFI_RUNTIME_SERVICES_DATA 6
|
|
+#define EFI_CONVENTIONAL_MEMORY 7
|
|
+#define EFI_UNUSABLE_MEMORY 8
|
|
+#define EFI_ACPI_RECLAIM_MEMORY 9
|
|
+#define EFI_ACPI_MEMORY_NVS 10
|
|
+#define EFI_MEMORY_MAPPED_IO 11
|
|
+#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12
|
|
+#define EFI_PAL_CODE 13
|
|
+#define EFI_MAX_MEMORY_TYPE 14
|
|
|
|
typedef struct {
|
|
uint64_t signature;
|
|
@@ -63,53 +101,171 @@ struct ia64_boot_param {
|
|
uint64_t initrd_size;
|
|
};
|
|
|
|
-void setup_arch(void)
|
|
+typedef struct {
|
|
+ uint32_t type;
|
|
+ uint32_t pad;
|
|
+ uint64_t phys_addr;
|
|
+ uint64_t virt_addr;
|
|
+ uint64_t num_pages;
|
|
+ uint64_t attribute;
|
|
+} efi_memory_desc_t;
|
|
+
|
|
+struct loaded_segment {
|
|
+ unsigned long start;
|
|
+ unsigned long end;
|
|
+ unsigned long reserved;
|
|
+};
|
|
+
|
|
+struct kexec_boot_params {
|
|
+ uint64_t ramdisk_base;
|
|
+ uint64_t ramdisk_size;
|
|
+ uint64_t command_line;
|
|
+ uint64_t command_line_len;
|
|
+ uint64_t efi_memmap_base;
|
|
+ uint64_t efi_memmap_size;
|
|
+ struct loaded_segment *loaded_segments;
|
|
+ unsigned long loaded_segments_num;
|
|
+};
|
|
+
|
|
+void
|
|
+setup_arch(void)
|
|
{
|
|
- /* Nothing for now */
|
|
+ reset_vga();
|
|
}
|
|
+
|
|
inline unsigned long PA(unsigned long addr)
|
|
{
|
|
return addr - PAGE_OFFSET;
|
|
}
|
|
|
|
-void flush_icache_range(char *start, unsigned long len)
|
|
+void
|
|
+patch_efi_memmap(struct kexec_boot_params *params,
|
|
+ struct ia64_boot_param *boot_param)
|
|
+{
|
|
+ void *dest = (void *)params->efi_memmap_base;
|
|
+ void *src = (void *)boot_param->efi_memmap;
|
|
+ unsigned long len = boot_param->efi_memmap_size;
|
|
+ unsigned long memdesc_size = boot_param->efi_memdesc_size;
|
|
+ uint64_t orig_type;
|
|
+ efi_memory_desc_t *md1, *md2;
|
|
+ void *p1, *p2, *src_end = src + len;
|
|
+ int i;
|
|
+ for (p1 = src, p2 = dest; p1 < src_end;
|
|
+ p1 += memdesc_size, p2 += memdesc_size) {
|
|
+ unsigned long mstart, mend;
|
|
+ md1 = p1;
|
|
+ md2 = p2;
|
|
+ if (md1->num_pages == 0)
|
|
+ continue;
|
|
+ mstart = md1->phys_addr;
|
|
+ mend = md1->phys_addr + (md1->num_pages
|
|
+ << EFI_PAGE_SHIFT);
|
|
+ switch (md1->type) {
|
|
+ case EFI_LOADER_DATA:
|
|
+ *md2 = *md1;
|
|
+ md2->type = EFI_CONVENTIONAL_MEMORY;
|
|
+ break;
|
|
+ default:
|
|
+ *md2 = *md1;
|
|
+ }
|
|
+ // segments are already sorted and aligned to 4K
|
|
+ orig_type = md2->type;
|
|
+ for (i = 0; i < params->loaded_segments_num; i++) {
|
|
+ struct loaded_segment *seg;
|
|
+ seg = ¶ms->loaded_segments[i];
|
|
+ if (seg->start >= mstart && seg->start < mend) {
|
|
+ unsigned long start_pages, mid_pages, end_pages;
|
|
+ if (seg->end > mend) {
|
|
+ p1 += memdesc_size;
|
|
+ for(; p1 < src_end;
|
|
+ p1 += memdesc_size) {
|
|
+ md1 = p1;
|
|
+ /* TODO check contig and attribute here */
|
|
+ mend = md1->phys_addr
|
|
+ + (md1->num_pages << EFI_PAGE_SHIFT);
|
|
+ if (seg->end < mend)
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ start_pages = (seg->start - mstart)
|
|
+ >> EFI_PAGE_SHIFT;
|
|
+ mid_pages = (seg->end - seg->start)
|
|
+ >> EFI_PAGE_SHIFT;
|
|
+ end_pages = (mend - seg->end)
|
|
+ >> EFI_PAGE_SHIFT;
|
|
+ if (start_pages) {
|
|
+ md2->num_pages = start_pages;
|
|
+ p2 += memdesc_size;
|
|
+ md2 = p2;
|
|
+ *md2 = *md1;
|
|
+ }
|
|
+ md2->phys_addr = seg->start;
|
|
+ md2->num_pages = mid_pages;
|
|
+ md2->type = seg->reserved ?
|
|
+ EFI_UNUSABLE_MEMORY:EFI_LOADER_DATA;
|
|
+ if (end_pages) {
|
|
+ p2 += memdesc_size;
|
|
+ md2 = p2;
|
|
+ *md2 = *md1;
|
|
+ md2->phys_addr = seg->end;
|
|
+ md2->num_pages = end_pages;
|
|
+ md2->type = orig_type;
|
|
+ mstart = seg->end;
|
|
+ } else
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ boot_param->efi_memmap_size = p2 - dest;
|
|
+}
|
|
+
|
|
+void
|
|
+flush_icache_range(char *start, unsigned long len)
|
|
{
|
|
unsigned long i;
|
|
for (i = 0;i < len; i += 32)
|
|
- asm volatile("fc.i %0"::"r"(start+i):"memory");
|
|
+ asm volatile("fc.i %0"::"r"(start + i):"memory");
|
|
asm volatile (";;sync.i;;":::"memory");
|
|
asm volatile ("srlz.i":::"memory");
|
|
}
|
|
|
|
extern char __dummy_efi_function[], __dummy_efi_function_end[];
|
|
|
|
-void ia64_env_setup(struct ia64_boot_param *boot_param,
|
|
- uint64_t command_line, uint64_t command_line_len,
|
|
- uint64_t ramdisk_base, uint64_t ramdisk_size)
|
|
+
|
|
+void
|
|
+ia64_env_setup(struct ia64_boot_param *boot_param,
|
|
+ struct kexec_boot_params *params)
|
|
{
|
|
unsigned long len;
|
|
efi_system_table_t *systab;
|
|
efi_runtime_services_t *runtime;
|
|
unsigned long *set_virtual_address_map;
|
|
+ char *command_line = (char *)params->command_line;
|
|
+ uint64_t command_line_len = params->command_line_len;
|
|
|
|
// patch efi_runtime->set_virtual_address_map to a
|
|
// dummy function
|
|
len = __dummy_efi_function_end - __dummy_efi_function;
|
|
- memcpy((char *)command_line + command_line_len, __dummy_efi_function,
|
|
- len);
|
|
+ memcpy(command_line + command_line_len,
|
|
+ __dummy_efi_function, len);
|
|
systab = (efi_system_table_t *)boot_param->efi_systab;
|
|
runtime = (efi_runtime_services_t *)PA(systab->runtime);
|
|
set_virtual_address_map =
|
|
(unsigned long *)PA(runtime->set_virtual_address_map);
|
|
- *(set_virtual_address_map)=
|
|
- (unsigned long)((char *)command_line + command_line_len);
|
|
- flush_icache_range((char *)command_line+command_line_len, len);
|
|
+ *(set_virtual_address_map) =
|
|
+ (unsigned long)(command_line + command_line_len);
|
|
+ flush_icache_range(command_line + command_line_len, len);
|
|
+
|
|
+ patch_efi_memmap(params, boot_param);
|
|
+
|
|
+ boot_param->efi_memmap = params->efi_memmap_base;
|
|
|
|
- boot_param->command_line = command_line;
|
|
+ boot_param->command_line = params->command_line;
|
|
boot_param->console_info.orig_x = 0;
|
|
boot_param->console_info.orig_y = 0;
|
|
- boot_param->initrd_start = ramdisk_base;
|
|
- boot_param->initrd_size = ramdisk_size;
|
|
+ boot_param->initrd_start = params->ramdisk_base;
|
|
+ boot_param->initrd_size = params->ramdisk_size;
|
|
}
|
|
|
|
/* This function can be used to execute after the SHA256 verification. */
|
|
diff -puN purgatory/arch/ia64/purgatory-ia64.h~kdump-ia64 purgatory/arch/ia64/purgatory-ia64.h
|
|
--- kexec-tools-1.101-kdump/purgatory/arch/ia64/purgatory-ia64.h~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
|
|
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/purgatory-ia64.h 2006-07-13 14:42:05.000000000 +0530
|
|
@@ -1,6 +1,5 @@
|
|
#ifndef PURGATORY_IA64_H
|
|
#define PURGATORY_IA64_H
|
|
|
|
-/* nothing yet */
|
|
-
|
|
+void reset_vga(void);
|
|
#endif /* PURGATORY_IA64_H */
|
|
diff -puN /dev/null purgatory/arch/ia64/vga.c
|
|
--- /dev/null 2006-07-13 05:14:41.629277080 +0530
|
|
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/vga.c 2006-07-13 14:42:05.000000000 +0530
|
|
@@ -0,0 +1,143 @@
|
|
+#include "io.h"
|
|
+void reset_vga(void)
|
|
+{
|
|
+ /* Hello */
|
|
+ inb(0x3da);
|
|
+ outb(0, 0x3c0);
|
|
+
|
|
+ /* Sequencer registers */
|
|
+ outw(0x0300, 0x3c4);
|
|
+ outw(0x0001, 0x3c4);
|
|
+ outw(0x0302, 0x3c4);
|
|
+ outw(0x0003, 0x3c4);
|
|
+ outw(0x0204, 0x3c4);
|
|
+
|
|
+ /* Ensure CRTC regs 0-7 are unlocked by clearing bit 7 of CRTC[17] */
|
|
+ outw(0x0e11, 0x3d4);
|
|
+ /* CRTC registers */
|
|
+ outw(0x5f00, 0x3d4);
|
|
+ outw(0x4f01, 0x3d4);
|
|
+ outw(0x5002, 0x3d4);
|
|
+ outw(0x8203, 0x3d4);
|
|
+ outw(0x5504, 0x3d4);
|
|
+ outw(0x8105, 0x3d4);
|
|
+ outw(0xbf06, 0x3d4);
|
|
+ outw(0x1f07, 0x3d4);
|
|
+ outw(0x0008, 0x3d4);
|
|
+ outw(0x4f09, 0x3d4);
|
|
+ outw(0x200a, 0x3d4);
|
|
+ outw(0x0e0b, 0x3d4);
|
|
+ outw(0x000c, 0x3d4);
|
|
+ outw(0x000d, 0x3d4);
|
|
+ outw(0x010e, 0x3d4);
|
|
+ outw(0xe00f, 0x3d4);
|
|
+ outw(0x9c10, 0x3d4);
|
|
+ outw(0x8e11, 0x3d4);
|
|
+ outw(0x8f12, 0x3d4);
|
|
+ outw(0x2813, 0x3d4);
|
|
+ outw(0x1f14, 0x3d4);
|
|
+ outw(0x9615, 0x3d4);
|
|
+ outw(0xb916, 0x3d4);
|
|
+ outw(0xa317, 0x3d4);
|
|
+ outw(0xff18, 0x3d4);
|
|
+
|
|
+ /* Graphic registers */
|
|
+ outw(0x0000, 0x3ce);
|
|
+ outw(0x0001, 0x3ce);
|
|
+ outw(0x0002, 0x3ce);
|
|
+ outw(0x0003, 0x3ce);
|
|
+ outw(0x0004, 0x3ce);
|
|
+ outw(0x1005, 0x3ce);
|
|
+ outw(0x0e06, 0x3ce);
|
|
+ outw(0x0007, 0x3ce);
|
|
+ outw(0xff08, 0x3ce);
|
|
+
|
|
+ /* Attribute registers */
|
|
+ inb(0x3da);
|
|
+ outb(0x00, 0x3c0);
|
|
+ outb(0x00, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x01, 0x3c0);
|
|
+ outb(0x01, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x02, 0x3c0);
|
|
+ outb(0x02, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x03, 0x3c0);
|
|
+ outb(0x03, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x04, 0x3c0);
|
|
+ outb(0x04, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x05, 0x3c0);
|
|
+ outb(0x05, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x06, 0x3c0);
|
|
+ outb(0x14, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x07, 0x3c0);
|
|
+ outb(0x07, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x08, 0x3c0);
|
|
+ outb(0x38, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x09, 0x3c0);
|
|
+ outb(0x39, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x0a, 0x3c0);
|
|
+ outb(0x3a, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x0b, 0x3c0);
|
|
+ outb(0x3b, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x0c, 0x3c0);
|
|
+ outb(0x3c, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x0d, 0x3c0);
|
|
+ outb(0x3d, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x0e, 0x3c0);
|
|
+ outb(0x3e, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x0f, 0x3c0);
|
|
+ outb(0x3f, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x10, 0x3c0);
|
|
+ outb(0x0c, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x11, 0x3c0);
|
|
+ outb(0x00, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x12, 0x3c0);
|
|
+ outb(0x0f, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x13, 0x3c0);
|
|
+ outb(0x08, 0x3c0);
|
|
+
|
|
+ inb(0x3da);
|
|
+ outb(0x14, 0x3c0);
|
|
+ outb(0x00, 0x3c0);
|
|
+
|
|
+ /* Goodbye */
|
|
+ inb(0x3da);
|
|
+ outb(0x20, 0x3c0);
|
|
+}
|
|
_
|