Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/Documentation/arm/SH-Mobile/vrl4.c
10821 views
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
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];
50
};
51
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) }
58
59
/* Align to 512 bytes, the MMCIF sector size */
60
#define ALIGN_BITS 9
61
#define ALIGN (1 << ALIGN_BITS)
62
63
#define START_BASE 0xe55b0000
64
65
/*
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.
71
*
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).
75
*/
76
#define MAX_BOOT_PROG_LEN (16 * 512)
77
78
#define ROUND_UP(x) ((x + ALIGN - 1) & ~(ALIGN - 1))
79
80
ssize_t do_read(int fd, void *buf, size_t count)
81
{
82
size_t offset = 0;
83
ssize_t l;
84
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;
94
}
95
offset += l;
96
}
97
98
return offset;
99
}
100
101
ssize_t do_write(int fd, const void *buf, size_t count)
102
{
103
size_t offset = 0;
104
ssize_t l;
105
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;
113
}
114
offset += l;
115
}
116
117
return offset;
118
}
119
120
ssize_t write_zero(int fd, size_t len)
121
{
122
size_t i = len;
123
124
while (i--) {
125
const char x = 0;
126
if (do_write(fd, &x, 1) < 0)
127
return -1;
128
}
129
130
return len;
131
}
132
133
int main(void)
134
{
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;
139
140
prog_len = do_read(0, boot_program, sizeof(boot_program));
141
if (prog_len <= 0)
142
return -1;
143
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);
148
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;
153
154
if (do_write(1, boot_program, prog_len) < 0)
155
return 1;
156
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;
166
}
167
168
return 0;
169
}
170
171