Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1b93b3c3 authored by Wu Zhangjin's avatar Wu Zhangjin Committed by Ralf Baechle
Browse files

MIPS: Add support for GZIP / BZIP2 / LZMA compressed kernel images



This patch helps to generate smaller kernel images for linux-MIPS,

Here is the effect when using lzma:

$ ls -sh vmlinux
7.1M vmlinux
$ ls -sh vmlinuz
1.5M vmlinuz

Have tested the 32bit kernel on Qemu/Malta and 64bit kernel on FuLoong
Mini PC. both of them work well. and also, tested by Alexander Clouter
on an AR7 based Linksys WAG54Gv2, and by Manuel Lauss on an Alchemy
board.

This -v2 version incorporate the feedback from Ralf, and add the
following changes:

1. add .ecoff, .bin, .erec format support
2. only enable it and the debug source code for the machines we tested
3. a dozen of fixups and cleanups

and if you want to enable it for your board, please try to select
SYS_SUPPORTS_ZBOOT for it, and if the board have an 16550 compatible
uart, you can select SYS_SUPPORTS_ZBOOT_UART16550 directly. and then
sending the relative patches to Ralf.

Tested-by: default avatarManuel Lauss <manuel.lauss@googlemail.com>
Tested-by: default avatarAlexander Clouter <alex@digriz.org.uk>
Signed-off-by: default avatarWu Zhangjin <wuzhangjin@gmail.com>
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent bea4c899
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ choice

config MACH_ALCHEMY
	bool "Alchemy processor based machines"
	select SYS_SUPPORTS_ZBOOT

config AR7
	bool "Texas Instruments AR7"
@@ -36,6 +37,7 @@ config AR7
	select SYS_HAS_EARLY_PRINTK
	select SYS_SUPPORTS_32BIT_KERNEL
	select SYS_SUPPORTS_LITTLE_ENDIAN
	select SYS_SUPPORTS_ZBOOT_UART16550
	select GENERIC_GPIO
	select GCD
	select VLYNQ
@@ -192,6 +194,7 @@ config LASAT

config MACH_LOONGSON
	bool "Loongson family of machines"
	select SYS_SUPPORTS_ZBOOT_UART16550
	help
	  This enables the support of Loongson family of machines.

@@ -233,6 +236,7 @@ config MIPS_MALTA
	select SYS_SUPPORTS_MIPS_CMP
	select SYS_SUPPORTS_MULTITHREADING
	select SYS_SUPPORTS_SMARTMIPS
	select SYS_SUPPORTS_ZBOOT
	help
	  This enables support for the MIPS Technologies Malta evaluation
	  board.
@@ -1294,6 +1298,16 @@ config CPU_CAVIUM_OCTEON

endchoice

config SYS_SUPPORTS_ZBOOT
	bool
	select HAVE_KERNEL_GZIP
	select HAVE_KERNEL_BZIP2
	select HAVE_KERNEL_LZMA

config SYS_SUPPORTS_ZBOOT_UART16550
	bool
	select SYS_SUPPORTS_ZBOOT

config CPU_LOONGSON2
	bool
	select CPU_SUPPORTS_32BIT_KERNEL
+28 −3
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ endif

all-$(CONFIG_BOOT_ELF32)	:= $(vmlinux-32)
all-$(CONFIG_BOOT_ELF64)	:= $(vmlinux-64)
all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlinuz

#
# GCC uses -G 0 -mabicalls -fpic as default.  We don't want PIC in the kernel
@@ -331,7 +332,7 @@ load-$(CONFIG_LEMOTE_FULOONG2E) +=0xffffffff80100000
core-$(CONFIG_MIPS_MALTA)	+= arch/mips/mti-malta/
cflags-$(CONFIG_MIPS_MALTA)	+= -I$(srctree)/arch/mips/include/asm/mach-malta
load-$(CONFIG_MIPS_MALTA)	+= 0xffffffff80100000
all-$(CONFIG_MIPS_MALTA)	:= vmlinux.bin
all-$(CONFIG_MIPS_MALTA)	:= vmlinuz.bin

#
# MIPS SIM
@@ -581,7 +582,7 @@ load-$(CONFIG_SNI_RM) += 0xffffffff80600000
else
load-$(CONFIG_SNI_RM)		+= 0xffffffff80030000
endif
all-$(CONFIG_SNI_RM)		:= vmlinux.ecoff
all-$(CONFIG_SNI_RM)		:= vmlinuz.ecoff

#
# Common TXx9
@@ -699,9 +700,23 @@ vmlinux.64: vmlinux
	$(OBJCOPY) -O $(64bit-bfd) $(OBJCOPYFLAGS) $< $@

makeboot =$(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) $(1)
makezboot =$(Q)$(MAKE) $(build)=arch/mips/boot/compressed \
	   VMLINUX_LOAD_ADDRESS=$(load-y) 32bit-bfd=$(32bit-bfd) $(1)

all:	$(all-y)

vmlinuz: vmlinux FORCE
	+@$(call makezboot,$@)

vmlinuz.bin: vmlinux
	+@$(call makezboot,$@)

vmlinuz.ecoff: vmlinux
	+@$(call makezboot,$@)

vmlinuz.srec: vmlinux
	+@$(call makezboot,$@)

vmlinux.bin: $(vmlinux-32)
	+@$(call makeboot,$@)

@@ -726,11 +741,13 @@ endif

install:
	$(Q)install -D -m 755 vmlinux $(INSTALL_PATH)/vmlinux-$(KERNELRELEASE)
	$(Q)install -D -m 755 vmlinuz $(INSTALL_PATH)/vmlinuz-$(KERNELRELEASE)
	$(Q)install -D -m 644 .config $(INSTALL_PATH)/config-$(KERNELRELEASE)
	$(Q)install -D -m 644 System.map $(INSTALL_PATH)/System.map-$(KERNELRELEASE)

archclean:
	@$(MAKE) $(clean)=arch/mips/boot
	@$(MAKE) $(clean)=arch/mips/boot/compressed
	@$(MAKE) $(clean)=arch/mips/lasat

define archhelp
@@ -738,10 +755,18 @@ define archhelp
	echo '  vmlinux.ecoff        - ECOFF boot image'
	echo '  vmlinux.bin          - Raw binary boot image'
	echo '  vmlinux.srec         - SREC boot image'
	echo '  vmlinuz              - Compressed boot(zboot) image'
	echo '  vmlinuz.ecoff        - ECOFF zboot image'
	echo '  vmlinuz.bin          - Raw binary zboot image'
	echo '  vmlinuz.srec         - SREC zboot image'
	echo
	echo '  These will be default as apropriate for a configured platform.'
endef

CLEAN_FILES += vmlinux.32 \
	       vmlinux.64 \
	       vmlinux.ecoff
	       vmlinux.ecoff \
	       vmlinuz \
	       vmlinuz.ecoff \
	       vmlinuz.bin \
	       vmlinuz.srec
+100 −0
Original line number Diff line number Diff line
#
# This file is subject to the terms and conditions of the GNU General Public
# License.
#
# Adapted for MIPS Pete Popov, Dan Malek
#
# Copyright (C) 1994 by Linus Torvalds
# Adapted for PowerPC by Gary Thomas
# modified by Cort (cort@cs.nmt.edu)
#
# Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University
# Author: Wu Zhangjin <wuzj@lemote.com>
#

# compressed kernel load addr: VMLINUZ_LOAD_ADDRESS > VMLINUX_LOAD_ADDRESS + VMLINUX_SIZE
VMLINUX_SIZE := $(shell wc -c $(objtree)/$(KBUILD_IMAGE) 2>/dev/null | cut -d' ' -f1)
VMLINUX_SIZE := $(shell [ -n "$(VMLINUX_SIZE)" ] && echo $$(($(VMLINUX_SIZE) + (65536 - $(VMLINUX_SIZE) % 65536))))
VMLINUZ_LOAD_ADDRESS := 0x$(shell [ -n "$(VMLINUX_SIZE)" ] && printf %x $$(($(VMLINUX_LOAD_ADDRESS) + $(VMLINUX_SIZE))))

# set the default size of the mallocing area for decompressing
BOOT_HEAP_SIZE := 0x400000

# Disable Function Tracer
KBUILD_CFLAGS := $(shell echo $(KBUILD_CFLAGS) | sed -e "s/-pg//")

KBUILD_CFLAGS := $(LINUXINCLUDE) $(KBUILD_CFLAGS) -D__KERNEL__ \
	-DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) -D"VMLINUX_LOAD_ADDRESS_ULL=$(VMLINUX_LOAD_ADDRESS)ull" \

KBUILD_AFLAGS := $(LINUXINCLUDE) $(KBUILD_AFLAGS) -D__ASSEMBLY__ \
	-DKERNEL_ENTRY=0x$(shell $(NM) $(objtree)/$(KBUILD_IMAGE) 2>/dev/null | grep " kernel_entry" | cut -f1 -d \ ) \
	-DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE)

obj-y := $(obj)/head.o $(obj)/decompress.o $(obj)/dbg.o

obj-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART16550) += $(obj)/uart-16550.o

OBJCOPYFLAGS_vmlinux.bin := $(OBJCOPYFLAGS) -O binary -R .comment -S
$(obj)/vmlinux.bin: $(KBUILD_IMAGE)
	$(call if_changed,objcopy)

suffix_$(CONFIG_KERNEL_GZIP)  = gz
suffix_$(CONFIG_KERNEL_BZIP2) = bz2
suffix_$(CONFIG_KERNEL_LZMA)  = lzma
tool_$(CONFIG_KERNEL_GZIP)    = gzip
tool_$(CONFIG_KERNEL_BZIP2)   = bzip2
tool_$(CONFIG_KERNEL_LZMA)    = lzma
$(obj)/vmlinux.$(suffix_y): $(obj)/vmlinux.bin
	$(call if_changed,$(tool_y))

$(obj)/piggy.o: $(obj)/vmlinux.$(suffix_y) $(obj)/dummy.o
	$(Q)$(OBJCOPY) $(OBJCOPYFLAGS) \
		--add-section=.image=$< \
		--set-section-flags=.image=contents,alloc,load,readonly,data \
		$(obj)/dummy.o $@

LDFLAGS_vmlinuz := $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T
vmlinuz: $(src)/ld.script $(obj-y) $(obj)/piggy.o
	$(call if_changed,ld)
	$(Q)$(OBJCOPY) $(OBJCOPYFLAGS) -R .comment -R .stab -R .stabstr -R .initrd -R .sysmap $@

#
# Some DECstations need all possible sections of an ECOFF executable
#
ifdef CONFIG_MACH_DECSTATION
  E2EFLAGS = -a
else
  E2EFLAGS =
endif

# elf2ecoff can only handle 32bit image

ifdef CONFIG_32BIT
	VMLINUZ = vmlinuz
else
	VMLINUZ = vmlinuz.32
endif

vmlinuz.32: vmlinuz
	$(Q)$(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@

vmlinuz.ecoff: $(obj)/../elf2ecoff $(VMLINUZ)
	$(Q)$(obj)/../elf2ecoff $(VMLINUZ) vmlinuz.ecoff $(E2EFLAGS)

$(obj)/../elf2ecoff: $(src)/../elf2ecoff.c
	$(Q)$(HOSTCC) -o $@ $^

drop-sections	= .reginfo .mdebug .comment .note .pdr .options .MIPS.options
strip-flags	= $(addprefix --remove-section=,$(drop-sections))

OBJCOPYFLAGS_vmlinuz.bin := $(OBJCOPYFLAGS) -O binary $(strip-flags)
vmlinuz.bin: vmlinuz
	$(call if_changed,objcopy)

OBJCOPYFLAGS_vmlinuz.srec := $(OBJCOPYFLAGS) -S -O srec $(strip-flags)
vmlinuz.srec: vmlinuz
	$(call if_changed,objcopy)

clean:
clean-files += *.o \
	       vmlinu*
+37 −0
Original line number Diff line number Diff line
/*
 * MIPS-specific debug support for pre-boot environment
 *
 * NOTE: putc() is board specific, if your board have a 16550 compatible uart,
 * please select SYS_SUPPORTS_ZBOOT_UART16550 for your machine. othewise, you
 * need to implement your own putc().
 */

#include <linux/init.h>
#include <linux/types.h>

void __attribute__ ((weak)) putc(char c)
{
}

void puts(const char *s)
{
	char c;
	while ((c = *s++) != '\0') {
		putc(c);
		if (c == '\n')
			putc('\r');
	}
}

void puthex(unsigned long long val)
{

	unsigned char buf[10];
	int i;
	for (i = 7; i >= 0; i--) {
		buf[i] = "0123456789ABCDEF"[val & 0x0F];
		val >>= 4;
	}
	buf[8] = '\0';
	puts(buf);
}
+126 −0
Original line number Diff line number Diff line
/*
 * Misc. bootloader code for many machines.
 *
 * Copyright 2001 MontaVista Software Inc.
 * Author: Matt Porter <mporter@mvista.com> Derived from
 * arch/ppc/boot/prep/misc.c
 *
 * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
 * Author: Wu Zhangjin <wuzj@lemote.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;  either version 2 of the  License, or (at your
 * option) any later version.
 */

#include <linux/types.h>
#include <linux/kernel.h>

#include <asm/addrspace.h>

/* These two variables specify the free mem region
 * that can be used for temporary malloc area
 */
unsigned long free_mem_ptr;
unsigned long free_mem_end_ptr;
char *zimage_start;

/* The linker tells us where the image is. */
extern unsigned char __image_begin, __image_end;
extern unsigned char __ramdisk_begin, __ramdisk_end;
unsigned long initrd_size;

/* debug interfaces  */
extern void puts(const char *s);
extern void puthex(unsigned long long val);

void error(char *x)
{
	puts("\n\n");
	puts(x);
	puts("\n\n -- System halted");

	while (1)
		;	/* Halt */
}

/* activate the code for pre-boot environment */
#define STATIC static

#ifdef CONFIG_KERNEL_GZIP
void *memcpy(void *dest, const void *src, size_t n)
{
	int i;
	const char *s = src;
	char *d = dest;

	for (i = 0; i < n; i++)
		d[i] = s[i];
	return dest;
}
#include "../../../../lib/decompress_inflate.c"
#endif

#ifdef CONFIG_KERNEL_BZIP2
void *memset(void *s, int c, size_t n)
{
	int i;
	char *ss = s;

	for (i = 0; i < n; i++)
		ss[i] = c;
	return s;
}
#include "../../../../lib/decompress_bunzip2.c"
#endif

#ifdef CONFIG_KERNEL_LZMA
#include "../../../../lib/decompress_unlzma.c"
#endif

void decompress_kernel(unsigned long boot_heap_start)
{
	int zimage_size;

	/*
	 * We link ourself to an arbitrary low address.  When we run, we
	 * relocate outself to that address.  __image_beign points to
	 * the part of the image where the zImage is. -- Tom
	 */
	zimage_start = (char *)(unsigned long)(&__image_begin);
	zimage_size = (unsigned long)(&__image_end) -
	    (unsigned long)(&__image_begin);

	/*
	 * The zImage and initrd will be between start and _end, so they've
	 * already been moved once.  We're good to go now. -- Tom
	 */
	puts("zimage at:     ");
	puthex((unsigned long)zimage_start);
	puts(" ");
	puthex((unsigned long)(zimage_size + zimage_start));
	puts("\n");

	if (initrd_size) {
		puts("initrd at:     ");
		puthex((unsigned long)(&__ramdisk_begin));
		puts(" ");
		puthex((unsigned long)(&__ramdisk_end));
		puts("\n");
	}

	/* this area are prepared for mallocing when decompressing */
	free_mem_ptr = boot_heap_start;
	free_mem_end_ptr = boot_heap_start + BOOT_HEAP_SIZE;

	/* Display standard Linux/MIPS boot prompt for kernel args */
	puts("Uncompressing Linux at load address ");
	puthex(VMLINUX_LOAD_ADDRESS_ULL);
	puts("\n");
	/* Decompress the kernel with according algorithm */
	decompress(zimage_start, zimage_size, 0, 0,
		   (void *)VMLINUX_LOAD_ADDRESS_ULL, 0, error);
	/* FIXME: is there a need to flush cache here? */
	puts("Now, booting the kernel...\n");
}
Loading