mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-09-18 06:39:27 +03:00
fc54b9bf15
(stable-branch of Openmoko) git-svn-id: svn://svn.openwrt.org/openwrt/trunk@13613 3c298f89-4303-0410-b956-a3cf2f4a3e73
317 lines
8.5 KiB
Diff
317 lines
8.5 KiB
Diff
From 68bcfea9ab5d8947f711a97dcc291cb9da47c7da Mon Sep 17 00:00:00 2001
|
|
From: mokopatches <mokopatches@openmoko.org>
|
|
Date: Sun, 13 Apr 2008 07:23:59 +0100
|
|
Subject: [PATCH] kexec-atags.patch
|
|
Leapfrogged from upstream (ARM Linux)
|
|
http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=4736/1
|
|
|
|
---
|
|
arch/arm/Kconfig | 7 +++
|
|
arch/arm/kernel/Makefile | 1 +
|
|
arch/arm/kernel/atags.c | 86 +++++++++++++++++++++++++++++++++++++
|
|
arch/arm/kernel/atags.h | 5 ++
|
|
arch/arm/kernel/machine_kexec.c | 2 +
|
|
arch/arm/kernel/relocate_kernel.S | 30 ++-----------
|
|
arch/arm/kernel/setup.c | 32 +-------------
|
|
include/asm-arm/kexec.h | 3 +
|
|
8 files changed, 110 insertions(+), 56 deletions(-)
|
|
create mode 100644 arch/arm/kernel/atags.c
|
|
create mode 100644 arch/arm/kernel/atags.h
|
|
|
|
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
|
|
index 23e3d6b..ef7b9ff 100644
|
|
--- a/arch/arm/Kconfig
|
|
+++ b/arch/arm/Kconfig
|
|
@@ -865,6 +865,13 @@ config KEXEC
|
|
initially work for you. It may help to enable device hotplugging
|
|
support.
|
|
|
|
+config ATAGS_PROC
|
|
+ bool "Export atags in procfs"
|
|
+ default n
|
|
+ help
|
|
+ Should the atags used to boot the kernel be exported in an "atags"
|
|
+ file in procfs. Useful with kexec.
|
|
+
|
|
endmenu
|
|
|
|
if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX )
|
|
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
|
|
index 593b565..5cf694c 100644
|
|
--- a/arch/arm/kernel/Makefile
|
|
+++ b/arch/arm/kernel/Makefile
|
|
@@ -19,6 +19,7 @@ obj-$(CONFIG_ISA_DMA) += dma-isa.o
|
|
obj-$(CONFIG_PCI) += bios32.o isa.o
|
|
obj-$(CONFIG_SMP) += smp.o
|
|
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
|
|
+obj-$(CONFIG_ATAGS_PROC) += atags.o
|
|
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
|
|
|
|
obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
|
|
diff --git a/arch/arm/kernel/atags.c b/arch/arm/kernel/atags.c
|
|
new file mode 100644
|
|
index 0000000..e2e934c
|
|
--- /dev/null
|
|
+++ b/arch/arm/kernel/atags.c
|
|
@@ -0,0 +1,86 @@
|
|
+#include <linux/slab.h>
|
|
+#include <linux/kexec.h>
|
|
+#include <linux/proc_fs.h>
|
|
+#include <asm/setup.h>
|
|
+#include <asm/types.h>
|
|
+#include <asm/page.h>
|
|
+
|
|
+struct buffer {
|
|
+ size_t size;
|
|
+ char *data;
|
|
+};
|
|
+static struct buffer tags_buffer;
|
|
+
|
|
+static int
|
|
+read_buffer(char* page, char** start, off_t off, int count,
|
|
+ int* eof, void* data)
|
|
+{
|
|
+ struct buffer *buffer = (struct buffer *)data;
|
|
+
|
|
+ if (off >= buffer->size) {
|
|
+ *eof = 1;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ count = min((int) (buffer->size - off), count);
|
|
+
|
|
+ memcpy(page, &buffer->data[off], count);
|
|
+
|
|
+ return count;
|
|
+}
|
|
+
|
|
+
|
|
+static int
|
|
+create_proc_entries(void)
|
|
+{
|
|
+ struct proc_dir_entry* tags_entry;
|
|
+
|
|
+ tags_entry = create_proc_read_entry("atags", 0400, &proc_root, read_buffer, &tags_buffer);
|
|
+ if (!tags_entry)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+static char __initdata atags_copy_buf[KEXEC_BOOT_PARAMS_SIZE];
|
|
+static char __initdata *atags_copy;
|
|
+
|
|
+void __init save_atags(const struct tag *tags)
|
|
+{
|
|
+ atags_copy = atags_copy_buf;
|
|
+ memcpy(atags_copy, tags, KEXEC_BOOT_PARAMS_SIZE);
|
|
+}
|
|
+
|
|
+
|
|
+static int __init init_atags_procfs(void)
|
|
+{
|
|
+ struct tag *tag;
|
|
+ int error;
|
|
+
|
|
+ if (!atags_copy) {
|
|
+ printk(KERN_WARNING "Exporting ATAGs: No saved tags found\n");
|
|
+ return -EIO;
|
|
+ }
|
|
+
|
|
+ for (tag = (struct tag *) atags_copy; tag->hdr.size; tag = tag_next(tag))
|
|
+ ;
|
|
+
|
|
+ tags_buffer.size = ((char *) tag - atags_copy) + sizeof(tag->hdr);
|
|
+ tags_buffer.data = kmalloc(tags_buffer.size, GFP_KERNEL);
|
|
+ if (tags_buffer.data == NULL)
|
|
+ return -ENOMEM;
|
|
+ memcpy(tags_buffer.data, atags_copy, tags_buffer.size);
|
|
+
|
|
+ error = create_proc_entries();
|
|
+ if (error) {
|
|
+ printk(KERN_ERR "Exporting ATAGs: not enough memory\n");
|
|
+ kfree(tags_buffer.data);
|
|
+ tags_buffer.size = 0;
|
|
+ tags_buffer.data = NULL;
|
|
+ }
|
|
+
|
|
+ return error;
|
|
+}
|
|
+
|
|
+arch_initcall(init_atags_procfs);
|
|
diff --git a/arch/arm/kernel/atags.h b/arch/arm/kernel/atags.h
|
|
new file mode 100644
|
|
index 0000000..e5f028d
|
|
--- /dev/null
|
|
+++ b/arch/arm/kernel/atags.h
|
|
@@ -0,0 +1,5 @@
|
|
+#ifdef CONFIG_ATAGS_PROC
|
|
+extern void save_atags(struct tag *tags);
|
|
+#else
|
|
+static inline void save_atags(struct tag *tags) { }
|
|
+#endif
|
|
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
|
|
index 863c664..db8f54a 100644
|
|
--- a/arch/arm/kernel/machine_kexec.c
|
|
+++ b/arch/arm/kernel/machine_kexec.c
|
|
@@ -21,6 +21,7 @@ extern void setup_mm_for_reboot(char mode);
|
|
extern unsigned long kexec_start_address;
|
|
extern unsigned long kexec_indirection_page;
|
|
extern unsigned long kexec_mach_type;
|
|
+extern unsigned long kexec_boot_atags;
|
|
|
|
/*
|
|
* Provide a dummy crash_notes definition while crash dump arrives to arm.
|
|
@@ -62,6 +63,7 @@ void machine_kexec(struct kimage *image)
|
|
kexec_start_address = image->start;
|
|
kexec_indirection_page = page_list;
|
|
kexec_mach_type = machine_arch_type;
|
|
+ kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET;
|
|
|
|
/* copy our kernel relocation code to the control code page */
|
|
memcpy(reboot_code_buffer,
|
|
diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S
|
|
index 062c111..61930eb 100644
|
|
--- a/arch/arm/kernel/relocate_kernel.S
|
|
+++ b/arch/arm/kernel/relocate_kernel.S
|
|
@@ -7,23 +7,6 @@
|
|
.globl relocate_new_kernel
|
|
relocate_new_kernel:
|
|
|
|
- /* Move boot params back to where the kernel expects them */
|
|
-
|
|
- ldr r0,kexec_boot_params_address
|
|
- teq r0,#0
|
|
- beq 8f
|
|
-
|
|
- ldr r1,kexec_boot_params_copy
|
|
- mov r6,#KEXEC_BOOT_PARAMS_SIZE/4
|
|
-7:
|
|
- ldr r5,[r1],#4
|
|
- str r5,[r0],#4
|
|
- subs r6,r6,#1
|
|
- bne 7b
|
|
-
|
|
-8:
|
|
- /* Boot params moved, now go on with the kernel */
|
|
-
|
|
ldr r0,kexec_indirection_page
|
|
ldr r1,kexec_start_address
|
|
|
|
@@ -67,7 +50,7 @@ relocate_new_kernel:
|
|
mov lr,r1
|
|
mov r0,#0
|
|
ldr r1,kexec_mach_type
|
|
- ldr r2,kexec_boot_params_address
|
|
+ ldr r2,kexec_boot_atags
|
|
mov pc,lr
|
|
|
|
.globl kexec_start_address
|
|
@@ -82,14 +65,9 @@ kexec_indirection_page:
|
|
kexec_mach_type:
|
|
.long 0x0
|
|
|
|
- /* phy addr where new kernel will expect to find boot params */
|
|
- .globl kexec_boot_params_address
|
|
-kexec_boot_params_address:
|
|
- .long 0x0
|
|
-
|
|
- /* phy addr where old kernel put a copy of orig boot params */
|
|
- .globl kexec_boot_params_copy
|
|
-kexec_boot_params_copy:
|
|
+ /* phy addr of the atags for the new kernel */
|
|
+ .globl kexec_boot_atags
|
|
+kexec_boot_atags:
|
|
.long 0x0
|
|
|
|
relocate_new_kernel_end:
|
|
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
|
|
index bf56eb3..ae3712d 100644
|
|
--- a/arch/arm/kernel/setup.c
|
|
+++ b/arch/arm/kernel/setup.c
|
|
@@ -24,7 +24,6 @@
|
|
#include <linux/interrupt.h>
|
|
#include <linux/smp.h>
|
|
#include <linux/fs.h>
|
|
-#include <linux/kexec.h>
|
|
|
|
#include <asm/cpu.h>
|
|
#include <asm/elf.h>
|
|
@@ -39,6 +38,7 @@
|
|
#include <asm/mach/time.h>
|
|
|
|
#include "compat.h"
|
|
+#include "atags.h"
|
|
|
|
#ifndef MEM_SIZE
|
|
#define MEM_SIZE (16*1024*1024)
|
|
@@ -784,23 +784,6 @@ static int __init customize_machine(void)
|
|
}
|
|
arch_initcall(customize_machine);
|
|
|
|
-#ifdef CONFIG_KEXEC
|
|
-
|
|
-/* Physical addr of where the boot params should be for this machine */
|
|
-extern unsigned long kexec_boot_params_address;
|
|
-
|
|
-/* Physical addr of the buffer into which the boot params are copied */
|
|
-extern unsigned long kexec_boot_params_copy;
|
|
-
|
|
-/* Pointer to the boot params buffer, for manipulation and display */
|
|
-unsigned long kexec_boot_params;
|
|
-EXPORT_SYMBOL(kexec_boot_params);
|
|
-
|
|
-/* The buffer itself - make sure it is sized correctly */
|
|
-static unsigned long kexec_boot_params_buf[(KEXEC_BOOT_PARAMS_SIZE + 3) / 4];
|
|
-
|
|
-#endif
|
|
-
|
|
void __init setup_arch(char **cmdline_p)
|
|
{
|
|
struct tag *tags = (struct tag *)&init_tags;
|
|
@@ -819,18 +802,6 @@ void __init setup_arch(char **cmdline_p)
|
|
else if (mdesc->boot_params)
|
|
tags = phys_to_virt(mdesc->boot_params);
|
|
|
|
-#ifdef CONFIG_KEXEC
|
|
- kexec_boot_params_copy = virt_to_phys(kexec_boot_params_buf);
|
|
- kexec_boot_params = (unsigned long)kexec_boot_params_buf;
|
|
- if (__atags_pointer) {
|
|
- kexec_boot_params_address = __atags_pointer;
|
|
- memcpy((void *)kexec_boot_params, tags, KEXEC_BOOT_PARAMS_SIZE);
|
|
- } else if (mdesc->boot_params) {
|
|
- kexec_boot_params_address = mdesc->boot_params;
|
|
- memcpy((void *)kexec_boot_params, tags, KEXEC_BOOT_PARAMS_SIZE);
|
|
- }
|
|
-#endif
|
|
-
|
|
/*
|
|
* If we have the old style parameters, convert them to
|
|
* a tag list.
|
|
@@ -846,6 +817,7 @@ void __init setup_arch(char **cmdline_p)
|
|
if (tags->hdr.tag == ATAG_CORE) {
|
|
if (meminfo.nr_banks != 0)
|
|
squash_mem_tags(tags);
|
|
+ save_atags(tags);
|
|
parse_tags(tags);
|
|
}
|
|
|
|
diff --git a/include/asm-arm/kexec.h b/include/asm-arm/kexec.h
|
|
index 46dcc4d..1ee17b6 100644
|
|
--- a/include/asm-arm/kexec.h
|
|
+++ b/include/asm-arm/kexec.h
|
|
@@ -16,6 +16,9 @@
|
|
|
|
#define KEXEC_BOOT_PARAMS_SIZE 1536
|
|
|
|
+#define KEXEC_ARM_ATAGS_OFFSET 0x1000
|
|
+#define KEXEC_ARM_ZIMAGE_OFFSET 0x8000
|
|
+
|
|
#ifndef __ASSEMBLY__
|
|
|
|
struct kimage;
|
|
--
|
|
1.5.6.5
|
|
|