Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[sfrench/cifs-2.6.git] / Documentation / arm / SH-Mobile / vrl4.c
1 /*
2  * vrl4 format generator
3  *
4  * Copyright (C) 2010 Simon Horman
5  *
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  */
10
11 /*
12  * usage: vrl4 < zImage > out
13  *        dd if=out of=/dev/sdx bs=512 seek=1 # Write the image to sector 1
14  *
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.
18  *
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.
22  *
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.
27  *
28  * The zImage is not modified in any way.
29  */
30
31 #define _BSD_SOURCE
32 #include <endian.h>
33 #include <unistd.h>
34 #include <stdint.h>
35 #include <stdio.h>
36 #include <errno.h>
37 #include <tools/endian.h>
38
39 struct hdr {
40         uint32_t magic1;
41         uint32_t reserved1;
42         uint32_t magic2;
43         uint32_t reserved2;
44         uint16_t copy_size;
45         uint16_t boot_options;
46         uint32_t reserved3;
47         uint32_t start_address;
48         uint32_t reserved4;
49         uint32_t reserved5;
50         char     reserved6[308];
51 };
52
53 #define DECLARE_HDR(h)                                  \
54         struct hdr (h) = {                              \
55                 .magic1 =       htole32(0xea000000),    \
56                 .reserved1 =    htole32(0x56),          \
57                 .magic2 =       htole32(0xe59ff008),    \
58                 .reserved3 =    htole16(0x1) }
59
60 /* Align to 512 bytes, the MMCIF sector size */
61 #define ALIGN_BITS      9
62 #define ALIGN           (1 << ALIGN_BITS)
63
64 #define START_BASE      0xe55b0000
65
66 /*
67  * With an alignment of 512 the header uses the first sector.
68  * There is a 128 sector (64kbyte) limit on the data loaded by the mask ROM.
69  * So there are 127 sectors left for the boot programme. But in practice
70  * Only a small portion of a zImage is needed, 16 sectors should be more
71  * than enough.
72  *
73  * Note that this sets how much of the zImage is copied by the mask ROM.
74  * The entire zImage is present after the header and is loaded
75  * by the code in the boot program (which is the first portion of the zImage).
76  */
77 #define MAX_BOOT_PROG_LEN (16 * 512)
78
79 #define ROUND_UP(x)     ((x + ALIGN - 1) & ~(ALIGN - 1))
80
81 static ssize_t do_read(int fd, void *buf, size_t count)
82 {
83         size_t offset = 0;
84         ssize_t l;
85
86         while (offset < count) {
87                 l = read(fd, buf + offset, count - offset);
88                 if (!l)
89                         break;
90                 if (l < 0) {
91                         if (errno == EAGAIN || errno == EWOULDBLOCK)
92                                 continue;
93                         perror("read");
94                         return -1;
95                 }
96                 offset += l;
97         }
98
99         return offset;
100 }
101
102 static ssize_t do_write(int fd, const void *buf, size_t count)
103 {
104         size_t offset = 0;
105         ssize_t l;
106
107         while (offset < count) {
108                 l = write(fd, buf + offset, count - offset);
109                 if (l < 0) {
110                         if (errno == EAGAIN || errno == EWOULDBLOCK)
111                                 continue;
112                         perror("write");
113                         return -1;
114                 }
115                 offset += l;
116         }
117
118         return offset;
119 }
120
121 static ssize_t write_zero(int fd, size_t len)
122 {
123         size_t i = len;
124
125         while (i--) {
126                 const char x = 0;
127                 if (do_write(fd, &x, 1) < 0)
128                         return -1;
129         }
130
131         return len;
132 }
133
134 int main(void)
135 {
136         DECLARE_HDR(hdr);
137         char boot_program[MAX_BOOT_PROG_LEN];
138         size_t aligned_hdr_len, alligned_prog_len;
139         ssize_t prog_len;
140
141         prog_len = do_read(0, boot_program, sizeof(boot_program));
142         if (prog_len <= 0)
143                 return -1;
144
145         aligned_hdr_len = ROUND_UP(sizeof(hdr));
146         hdr.start_address = htole32(START_BASE + aligned_hdr_len);
147         alligned_prog_len = ROUND_UP(prog_len);
148         hdr.copy_size = htole16(aligned_hdr_len + alligned_prog_len);
149
150         if (do_write(1, &hdr, sizeof(hdr)) < 0)
151                 return -1;
152         if (write_zero(1, aligned_hdr_len - sizeof(hdr)) < 0)
153                 return -1;
154
155         if (do_write(1, boot_program, prog_len) < 0)
156                 return 1;
157
158         /* Write out the rest of the kernel */
159         while (1) {
160                 prog_len = do_read(0, boot_program, sizeof(boot_program));
161                 if (prog_len < 0)
162                         return 1;
163                 if (prog_len == 0)
164                         break;
165                 if (do_write(1, boot_program, prog_len) < 0)
166                         return 1;
167         }
168
169         return 0;
170 }