Blame view
tools/mksunxiboot.c
4.65 KB
83d290c56 SPDX: Convert all... |
1 |
// SPDX-License-Identifier: GPL-2.0+ |
50827a599 sunxi: non-FEL SP... |
2 3 4 5 6 7 |
/* * (C) Copyright 2007-2011 * Allwinner Technology Co., Ltd. <www.allwinnertech.com> * Tom Cubie <tangliang@allwinnertech.com> * * a simple tool to generate bootable image for sunxi platform. |
50827a599 sunxi: non-FEL SP... |
8 9 10 11 12 13 14 15 16 |
*/ #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> |
fed329aeb tools: add mksunx... |
17 |
#include "../arch/arm/include/asm/arch-sunxi/spl.h" |
50827a599 sunxi: non-FEL SP... |
18 |
|
50827a599 sunxi: non-FEL SP... |
19 20 21 22 23 24 25 26 27 28 |
#define STAMP_VALUE 0x5F0A6C39 /* check sum functon from sun4i boot code */ int gen_check_sum(struct boot_file_head *head_p) { uint32_t length; uint32_t *buf; uint32_t loop; uint32_t i; uint32_t sum; |
c924e2a80 tools: mksunxiboo... |
29 |
length = le32_to_cpu(head_p->length); |
50827a599 sunxi: non-FEL SP... |
30 31 32 |
if ((length & 0x3) != 0) /* must 4-byte-aligned */ return -1; buf = (uint32_t *)head_p; |
c924e2a80 tools: mksunxiboo... |
33 |
head_p->check_sum = cpu_to_le32(STAMP_VALUE); /* fill stamp */ |
50827a599 sunxi: non-FEL SP... |
34 35 36 37 |
loop = length >> 2; /* calculate the sum */ for (i = 0, sum = 0; i < loop; i++) |
c924e2a80 tools: mksunxiboo... |
38 |
sum += le32_to_cpu(buf[i]); |
50827a599 sunxi: non-FEL SP... |
39 40 |
/* write back check sum */ |
c924e2a80 tools: mksunxiboo... |
41 |
head_p->check_sum = cpu_to_le32(sum); |
50827a599 sunxi: non-FEL SP... |
42 43 44 45 46 47 |
return 0; } #define ALIGN(x, a) __ALIGN_MASK((x), (typeof(x))(a)-1) #define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) |
45e2d0676 tools: mksunxiboo... |
48 49 |
#define SUNXI_SRAM_SIZE 0x8000 /* SoC with smaller size are limited before */ #define SRAM_LOAD_MAX_SIZE (SUNXI_SRAM_SIZE - sizeof(struct boot_file_head)) |
1f6f61fe4 sunxi/nand: chang... |
50 51 52 53 54 55 56 |
/* * BROM (at least on A10 and A20) requires NAND-images to be explicitly aligned * to a multiple of 8K, and rejects the image otherwise. MMC-images are fine * with 512B blocks. To cater for both, align to the largest of the two. */ #define BLOCK_SIZE 0x2000 |
50827a599 sunxi: non-FEL SP... |
57 58 59 60 61 62 63 64 65 66 67 |
struct boot_img { struct boot_file_head header; char code[SRAM_LOAD_MAX_SIZE]; char pad[BLOCK_SIZE]; }; int main(int argc, char *argv[]) { int fd_in, fd_out; struct boot_img img; |
4ba73a5ac sunxi: mksunxiboo... |
68 |
unsigned file_size; |
50827a599 sunxi: non-FEL SP... |
69 |
int count; |
7f0ef5a94 sunxi: Store the ... |
70 71 |
char *tool_name = argv[0]; char *default_dt = NULL; |
50827a599 sunxi: non-FEL SP... |
72 |
|
7f0ef5a94 sunxi: Store the ... |
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
/* a sanity check */ if ((sizeof(img.header) % 32) != 0) { fprintf(stderr, "ERROR: the SPL header must be a multiple "); fprintf(stderr, "of 32 bytes. "); return EXIT_FAILURE; } /* process optional command line switches */ while (argc >= 2 && argv[1][0] == '-') { if (strcmp(argv[1], "--default-dt") == 0) { if (argc >= 3) { default_dt = argv[2]; argv += 2; argc -= 2; continue; } fprintf(stderr, "ERROR: no --default-dt arg "); return EXIT_FAILURE; } else { fprintf(stderr, "ERROR: bad option '%s' ", argv[1]); return EXIT_FAILURE; } } if (argc < 3) { printf("This program converts an input binary file to a sunxi bootable image. "); printf(" Usage: %s [options] input_file output_file ", tool_name); printf("Where [options] may be: "); printf(" --default-dt arg - 'arg' is the default device tree name "); printf(" (CONFIG_DEFAULT_DEVICE_TREE). "); |
50827a599 sunxi: non-FEL SP... |
113 114 115 116 117 118 119 120 |
return EXIT_FAILURE; } fd_in = open(argv[1], O_RDONLY); if (fd_in < 0) { perror("Open input file"); return EXIT_FAILURE; } |
bfb05d018 sunxi: Ensure tha... |
121 |
memset(&img, 0, sizeof(img)); |
50827a599 sunxi: non-FEL SP... |
122 123 124 125 126 127 128 129 |
/* get input file size */ file_size = lseek(fd_in, 0, SEEK_END); if (file_size > SRAM_LOAD_MAX_SIZE) { fprintf(stderr, "ERROR: File too large! "); return EXIT_FAILURE; |
50827a599 sunxi: non-FEL SP... |
130 131 132 133 134 135 136 137 138 139 |
} fd_out = open(argv[2], O_WRONLY | O_CREAT, 0666); if (fd_out < 0) { perror("Open output file"); return EXIT_FAILURE; } /* read file to buffer to calculate checksum */ lseek(fd_in, 0, SEEK_SET); |
4ba73a5ac sunxi: mksunxiboo... |
140 141 |
count = read(fd_in, img.code, file_size); if (count != file_size) { |
50827a599 sunxi: non-FEL SP... |
142 143 144 145 146 147 148 149 150 151 152 |
perror("Reading input image"); return EXIT_FAILURE; } /* fill the header */ img.header.b_instruction = /* b instruction */ 0xEA000000 | /* jump to the first instr after the header */ ((sizeof(struct boot_file_head) / sizeof(int) - 2) & 0x00FFFFFF); memcpy(img.header.magic, BOOT0_MAGIC, 8); /* no '0' termination */ img.header.length = |
4ba73a5ac sunxi: mksunxiboo... |
153 |
ALIGN(file_size + sizeof(struct boot_file_head), BLOCK_SIZE); |
c924e2a80 tools: mksunxiboo... |
154 155 |
img.header.b_instruction = cpu_to_le32(img.header.b_instruction); img.header.length = cpu_to_le32(img.header.length); |
a18843817 sunxi: (mksunxibo... |
156 157 158 |
memcpy(img.header.spl_signature, SPL_SIGNATURE, 3); /* "sunxi" marker */ img.header.spl_signature[3] = SPL_HEADER_VERSION; |
7f0ef5a94 sunxi: Store the ... |
159 160 161 162 163 164 165 166 167 168 169 170 171 |
if (default_dt) { if (strlen(default_dt) + 1 <= sizeof(img.header.string_pool)) { strcpy((char *)img.header.string_pool, default_dt); img.header.dt_name_offset = cpu_to_le32(offsetof(struct boot_file_head, string_pool)); } else { printf("WARNING: The SPL header is too small "); printf(" and has no space to store the dt name. "); } } |
50827a599 sunxi: non-FEL SP... |
172 |
gen_check_sum(&img.header); |
c924e2a80 tools: mksunxiboo... |
173 174 |
count = write(fd_out, &img, le32_to_cpu(img.header.length)); if (count != le32_to_cpu(img.header.length)) { |
50827a599 sunxi: non-FEL SP... |
175 176 177 178 179 180 181 182 183 |
perror("Writing output"); return EXIT_FAILURE; } close(fd_in); close(fd_out); return EXIT_SUCCESS; } |