Based on kernel version 4.0. Page generated on 2015-04-14 21:19 EST.
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 }