diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-16 19:03:06 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-16 19:03:06 -0700 |
commit | 16d8775700f1815076f879719ce14b33f50a3171 (patch) | |
tree | 8525e6e6f12b6acf7cf2746853cc65549f3dbf4c /Documentation/arm/SH-Mobile/vrl4.c | |
parent | e34551339a195aa548eaf698523714a8fe7f1984 (diff) | |
parent | 05e34754518b6a90d5c392790c032575fab12d66 (diff) |
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (91 commits)
ARM: 6806/1: irq: introduce entry and exit functions for chained handlers
ARM: 6781/1: Thumb-2: Work around buggy Thumb-2 short branch relocations in gas
ARM: 6747/1: P2V: Thumb2 support
ARM: 6798/1: aout-core: zero thread debug registers in a.out core dump
ARM: 6796/1: Footbridge: Fix I/O mappings for NOMMU mode
ARM: 6784/1: errata: no automatic Store Buffer drain on Cortex-A9
ARM: 6772/1: errata: possible fault MMU translations following an ASID switch
ARM: 6776/1: mach-ux500: activate fix for errata 753970
ARM: 6794/1: SPEAr: Append UL to device address macros.
ARM: 6793/1: SPEAr: Remove unused *_SIZE macros from spear*.h files
ARM: 6792/1: SPEAr: Replace SIZE macro's with SZ_4K macros
ARM: 6791/1: SPEAr3xx: Declare device structures after shirq code
ARM: 6790/1: SPEAr: Clock Framework: Rename usbd clock and align apb_clk entry
ARM: 6789/1: SPEAr3xx: Rename sdio to sdhci
ARM: 6788/1: SPEAr: Include mach/hardware.h instead of mach/spear.h
ARM: 6787/1: SPEAr: Reorder #includes in .h & .c files.
ARM: 6681/1: SPEAr: add debugfs support to clk API
ARM: 6703/1: SPEAr: update clk API support
ARM: 6679/1: SPEAr: make clk API functions more generic
ARM: 6737/1: SPEAr: formalized timer support
...
Diffstat (limited to 'Documentation/arm/SH-Mobile/vrl4.c')
-rw-r--r-- | Documentation/arm/SH-Mobile/vrl4.c | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/Documentation/arm/SH-Mobile/vrl4.c b/Documentation/arm/SH-Mobile/vrl4.c new file mode 100644 index 000000000000..e8a191358ad2 --- /dev/null +++ b/Documentation/arm/SH-Mobile/vrl4.c @@ -0,0 +1,169 @@ +/* + * vrl4 format generator + * + * Copyright (C) 2010 Simon Horman + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +/* + * usage: vrl4 < zImage > out + * dd if=out of=/dev/sdx bs=512 seek=1 # Write the image to sector 1 + * + * Reads a zImage from stdin and writes a vrl4 image to stdout. + * In practice this means writing a padded vrl4 header to stdout followed + * by the zImage. + * + * The padding places the zImage at ALIGN bytes into the output. + * The vrl4 uses ALIGN + START_BASE as the start_address. + * This is where the mask ROM will jump to after verifying the header. + * + * The header sets copy_size to min(sizeof(zImage), MAX_BOOT_PROG_LEN) + ALIGN. + * That is, the mask ROM will load the padded header (ALIGN bytes) + * And then MAX_BOOT_PROG_LEN bytes of the image, or the entire image, + * whichever is smaller. + * + * The zImage is not modified in any way. + */ + +#define _BSD_SOURCE +#include <endian.h> +#include <unistd.h> +#include <stdint.h> +#include <stdio.h> +#include <errno.h> + +struct hdr { + uint32_t magic1; + uint32_t reserved1; + uint32_t magic2; + uint32_t reserved2; + uint16_t copy_size; + uint16_t boot_options; + uint32_t reserved3; + uint32_t start_address; + uint32_t reserved4; + uint32_t reserved5; + char reserved6[308]; +}; + +#define DECLARE_HDR(h) \ + struct hdr (h) = { \ + .magic1 = htole32(0xea000000), \ + .reserved1 = htole32(0x56), \ + .magic2 = htole32(0xe59ff008), \ + .reserved3 = htole16(0x1) } + +/* Align to 512 bytes, the MMCIF sector size */ +#define ALIGN_BITS 9 +#define ALIGN (1 << ALIGN_BITS) + +#define START_BASE 0xe55b0000 + +/* + * With an alignment of 512 the header uses the first sector. + * There is a 128 sector (64kbyte) limit on the data loaded by the mask ROM. + * So there are 127 sectors left for the boot programme. But in practice + * Only a small portion of a zImage is needed, 16 sectors should be more + * than enough. + * + * Note that this sets how much of the zImage is copied by the mask ROM. + * The entire zImage is present after the header and is loaded + * by the code in the boot program (which is the first portion of the zImage). + */ +#define MAX_BOOT_PROG_LEN (16 * 512) + +#define ROUND_UP(x) ((x + ALIGN - 1) & ~(ALIGN - 1)) + +ssize_t do_read(int fd, void *buf, size_t count) +{ + size_t offset = 0; + ssize_t l; + + while (offset < count) { + l = read(fd, buf + offset, count - offset); + if (!l) + break; + if (l < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) + continue; + perror("read"); + return -1; + } + offset += l; + } + + return offset; +} + +ssize_t do_write(int fd, const void *buf, size_t count) +{ + size_t offset = 0; + ssize_t l; + + while (offset < count) { + l = write(fd, buf + offset, count - offset); + if (l < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) + continue; + perror("write"); + return -1; + } + offset += l; + } + + return offset; +} + +ssize_t write_zero(int fd, size_t len) +{ + size_t i = len; + + while (i--) { + const char x = 0; + if (do_write(fd, &x, 1) < 0) + return -1; + } + + return len; +} + +int main(void) +{ + DECLARE_HDR(hdr); + char boot_program[MAX_BOOT_PROG_LEN]; + size_t aligned_hdr_len, alligned_prog_len; + ssize_t prog_len; + + prog_len = do_read(0, boot_program, sizeof(boot_program)); + if (prog_len <= 0) + return -1; + + aligned_hdr_len = ROUND_UP(sizeof(hdr)); + hdr.start_address = htole32(START_BASE + aligned_hdr_len); + alligned_prog_len = ROUND_UP(prog_len); + hdr.copy_size = htole16(aligned_hdr_len + alligned_prog_len); + + if (do_write(1, &hdr, sizeof(hdr)) < 0) + return -1; + if (write_zero(1, aligned_hdr_len - sizeof(hdr)) < 0) + return -1; + + if (do_write(1, boot_program, prog_len) < 0) + return 1; + + /* Write out the rest of the kernel */ + while (1) { + prog_len = do_read(0, boot_program, sizeof(boot_program)); + if (prog_len < 0) + return 1; + if (prog_len == 0) + break; + if (do_write(1, boot_program, prog_len) < 0) + return 1; + } + + return 0; +} |