Merge branch 'akpm'
[linux-2.6/next.git] / Documentation / arm / SH-Mobile / vrl4.c
blobe8a191358ad235485c28e7ac57ca06155b00d1fa
1 /*
2 * vrl4 format generator
4 * Copyright (C) 2010 Simon Horman
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
12 * usage: vrl4 < zImage > out
13 * dd if=out of=/dev/sdx bs=512 seek=1 # Write the image to sector 1
15 * Reads a zImage from stdin and writes a vrl4 image to stdout.
16 * In practice this means writing a padded vrl4 header to stdout followed
17 * by the zImage.
19 * The padding places the zImage at ALIGN bytes into the output.
20 * The vrl4 uses ALIGN + START_BASE as the start_address.
21 * This is where the mask ROM will jump to after verifying the header.
23 * The header sets copy_size to min(sizeof(zImage), MAX_BOOT_PROG_LEN) + ALIGN.
24 * That is, the mask ROM will load the padded header (ALIGN bytes)
25 * And then MAX_BOOT_PROG_LEN bytes of the image, or the entire image,
26 * whichever is smaller.
28 * The zImage is not modified in any way.
31 #define _BSD_SOURCE
32 #include <endian.h>
33 #include <unistd.h>
34 #include <stdint.h>
35 #include <stdio.h>
36 #include <errno.h>
38 struct hdr {
39 uint32_t magic1;
40 uint32_t reserved1;
41 uint32_t magic2;
42 uint32_t reserved2;
43 uint16_t copy_size;
44 uint16_t boot_options;
45 uint32_t reserved3;
46 uint32_t start_address;
47 uint32_t reserved4;
48 uint32_t reserved5;
49 char reserved6[308];
52 #define DECLARE_HDR(h) \
53 struct hdr (h) = { \
54 .magic1 = htole32(0xea000000), \
55 .reserved1 = htole32(0x56), \
56 .magic2 = htole32(0xe59ff008), \
57 .reserved3 = htole16(0x1) }
59 /* Align to 512 bytes, the MMCIF sector size */
60 #define ALIGN_BITS 9
61 #define ALIGN (1 << ALIGN_BITS)
63 #define START_BASE 0xe55b0000
66 * With an alignment of 512 the header uses the first sector.
67 * There is a 128 sector (64kbyte) limit on the data loaded by the mask ROM.
68 * So there are 127 sectors left for the boot programme. But in practice
69 * Only a small portion of a zImage is needed, 16 sectors should be more
70 * than enough.
72 * Note that this sets how much of the zImage is copied by the mask ROM.
73 * The entire zImage is present after the header and is loaded
74 * by the code in the boot program (which is the first portion of the zImage).
76 #define MAX_BOOT_PROG_LEN (16 * 512)
78 #define ROUND_UP(x) ((x + ALIGN - 1) & ~(ALIGN - 1))
80 ssize_t do_read(int fd, void *buf, size_t count)
82 size_t offset = 0;
83 ssize_t l;
85 while (offset < count) {
86 l = read(fd, buf + offset, count - offset);
87 if (!l)
88 break;
89 if (l < 0) {
90 if (errno == EAGAIN || errno == EWOULDBLOCK)
91 continue;
92 perror("read");
93 return -1;
95 offset += l;
98 return offset;
101 ssize_t do_write(int fd, const void *buf, size_t count)
103 size_t offset = 0;
104 ssize_t l;
106 while (offset < count) {
107 l = write(fd, buf + offset, count - offset);
108 if (l < 0) {
109 if (errno == EAGAIN || errno == EWOULDBLOCK)
110 continue;
111 perror("write");
112 return -1;
114 offset += l;
117 return offset;
120 ssize_t write_zero(int fd, size_t len)
122 size_t i = len;
124 while (i--) {
125 const char x = 0;
126 if (do_write(fd, &x, 1) < 0)
127 return -1;
130 return len;
133 int main(void)
135 DECLARE_HDR(hdr);
136 char boot_program[MAX_BOOT_PROG_LEN];
137 size_t aligned_hdr_len, alligned_prog_len;
138 ssize_t prog_len;
140 prog_len = do_read(0, boot_program, sizeof(boot_program));
141 if (prog_len <= 0)
142 return -1;
144 aligned_hdr_len = ROUND_UP(sizeof(hdr));
145 hdr.start_address = htole32(START_BASE + aligned_hdr_len);
146 alligned_prog_len = ROUND_UP(prog_len);
147 hdr.copy_size = htole16(aligned_hdr_len + alligned_prog_len);
149 if (do_write(1, &hdr, sizeof(hdr)) < 0)
150 return -1;
151 if (write_zero(1, aligned_hdr_len - sizeof(hdr)) < 0)
152 return -1;
154 if (do_write(1, boot_program, prog_len) < 0)
155 return 1;
157 /* Write out the rest of the kernel */
158 while (1) {
159 prog_len = do_read(0, boot_program, sizeof(boot_program));
160 if (prog_len < 0)
161 return 1;
162 if (prog_len == 0)
163 break;
164 if (do_write(1, boot_program, prog_len) < 0)
165 return 1;
168 return 0;