===================================================================
@@ -0,0 +1,58 @@
+/*
+ * Handling of arch specific bits in the decompressor
+ *
+ * Copyright (C) 2012 Domenico Andreoli <domenico.andreoli@linux.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#ifndef LINUX_DECOMP_ARCH_H
+#define LINUX_DECOMP_ARCH_H
+
+#include <linux/init.h>
+
+enum decomp_tag_type {
+ DECOMP_TAG_ARCH = 0,
+};
+
+struct decomp_tag_hdr {
+ unsigned int arch_id;
+ unsigned short type;
+ unsigned short size;
+};
+
+#define DECOMP_TAG_START(_struct, _name, _tagtype, _machid) \
+static const _struct _name __used \
+ __attribute__((__section__(".arch.tags.decomp"))) = { \
+ .hdr = { \
+ .arch_id = _machid, \
+ .type = _tagtype, \
+ .size = sizeof(_struct), \
+ },
+
+#define DECOMP_TAG_END \
+};
+
+struct decomp_arch_tag {
+ struct decomp_tag_hdr hdr;
+ void (*setup)(void);
+ void (*error)(char *msg);
+};
+
+#define DECOMP_ARCH_START(_machid) \
+DECOMP_TAG_START(struct decomp_arch_tag, __decomp_arch_##_machid, \
+ DECOMP_TAG_ARCH, MACH_TYPE_##_machid)
+
+#define DECOMP_ARCH_END DECOMP_TAG_END
+
+#define __decomp_arch __section(.arch.text.decomp)
+#define __decomp_archdata __section(.arch.data.decomp)
+
+#endif /* LINUX_DECOMP_ARCH_H */
===================================================================
@@ -16,8 +16,6 @@
* This allows for a much quicker boot time.
*/
-unsigned int __machine_arch_type;
-
#include <linux/compiler.h> /* for inline */
#include <linux/types.h>
#include <linux/linkage.h>
@@ -29,6 +27,10 @@ void error(char *x);
#include <mach/uncompress.h>
#endif
+#include <linux/decompress/arch.h>
+
+#include "arch.h"
+
#ifdef CONFIG_DEBUG_ICEDCC
#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
@@ -134,12 +136,10 @@ extern char input_data_end[];
unsigned char *output_data;
-unsigned long free_mem_ptr;
-unsigned long free_mem_end_ptr;
-
void error(char *x)
{
- fallback_arch_error(x);
+ if (arch_error_p)
+ arch_error_p(x);
putstr("\n\n");
putstr(x);
@@ -157,18 +157,11 @@ extern int do_decompress(u8 *input, int
void
-decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
- unsigned long free_mem_ptr_end_p,
- int arch_id)
+decompress_kernel(unsigned long output_start)
{
int ret;
- output_data = (unsigned char *)output_start;
- free_mem_ptr = free_mem_ptr_p;
- free_mem_end_ptr = free_mem_ptr_end_p;
- __machine_arch_type = arch_id;
-
- fallback_arch_setup();
+ output_data = (unsigned char *)output_start;
putstr("Uncompressing Linux...");
ret = do_decompress(input_data, input_data_end - input_data,
===================================================================
@@ -447,14 +447,14 @@ not_relocated: mov r0, #0
/*
* The C runtime environment should now be setup sufficiently.
* Set up some pointers, and start decompressing.
- * r4 = kernel execution address
- * r7 = architecture ID
- * r8 = atags pointer
*/
- mov r0, r4
- mov r1, sp @ malloc space above stack
- add r2, sp, #0x10000 @ 64k max
- mov r3, r7
+
+ mov r0, r7 @ architecture id
+ mov r1, r8 @ atags or devicetree
+ mov r2, sp @ malloc space above stack
+ add r3, sp, #0x10000 @ 64k max
+ bl arch_setup
+ mov r0, r4 @ kernel execution address
bl decompress_kernel
bl cache_clean_flush
bl cache_off
===================================================================
@@ -13,10 +13,22 @@
* GNU General Public License for more details.
*/
+unsigned int __machine_arch_type;
+
+#include <linux/compiler.h>
#include <linux/types.h>
+#include <linux/linkage.h>
+#include <linux/string.h>
+
+#include <linux/decompress/arch.h>
#include "arch.h"
+unsigned long free_mem_ptr;
+unsigned long free_mem_end_ptr;
+
+void (*arch_error_p)(char *x);
+
/* defined in the linker script */
extern void *__decomp_text_begin;
extern void *__decomp_data_begin;
@@ -36,3 +48,44 @@ const void *fix_data_ptr(const void *p)
return ((void *) &__decomp_data_begin) + (p - __decomp_data_begin);
}
+
+extern const struct decomp_tag_hdr __decomp_tags_begin[];
+extern const struct decomp_tag_hdr __decomp_tags_end[];
+
+#define for_each_decomp_tag(p) \
+ for ((p) = __decomp_tags_begin; \
+ (p) < __decomp_tags_end; \
+ p = ((void *) p) + (p)->size)
+
+void arch_setup(unsigned int arch_id, void *atag_fdt,
+ unsigned long free_mem_ptr_p,
+ unsigned long free_mem_ptr_end_p)
+{
+ struct decomp_arch_tag *arch_tag = NULL;
+ const struct decomp_tag_hdr *hdr;
+ void (*arch_setup_p)(void);
+
+ __machine_arch_type = arch_id;
+
+ arch_setup_p = fallback_arch_setup;
+ arch_error_p = fallback_arch_error;
+
+ free_mem_ptr = free_mem_ptr_p;
+ free_mem_end_ptr = free_mem_ptr_end_p;
+
+ for_each_decomp_tag(hdr) {
+ if (hdr->arch_id != arch_id)
+ continue;
+
+ if (hdr->type == DECOMP_TAG_ARCH) {
+ arch_tag = (struct decomp_arch_tag *) hdr;
+ arch_setup_p = fix_text_ptr(arch_tag->setup);
+ arch_error_p = fix_text_ptr(arch_tag->error);
+ break;
+ }
+ }
+
+ /* archs without decompressor setup have NULL here */
+ if (arch_setup_p)
+ arch_setup_p();
+}
===================================================================
@@ -16,6 +16,16 @@
#ifndef ARM_BOOT_COMPRESSED_ARCH_H
#define ARM_BOOT_COMPRESSED_ARCH_H
+extern unsigned int __machine_arch_type;
+
+extern unsigned long free_mem_ptr;
+extern unsigned long free_mem_end_ptr;
+
+extern void (*arch_error_p)(char *x);
+
+void fallback_arch_setup(void);
+void fallback_arch_error(char *x);
+
const void *fix_text_ptr(const void *p);
const void *fix_data_ptr(const void *p);