-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmksunxiboot.c
170 lines (146 loc) · 5.19 KB
/
mksunxiboot.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*
* modified by Liu Peiyuan
* email: peiyuanix@gmail.com
* date: 2023/10/14
*
* (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.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#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>
typedef unsigned char u8;
typedef unsigned int u32;
/* boot head definition from sun4i boot code */
typedef struct __attribute__((packed)) boot_file_head
{
u32 jump_instruction; // one intruction jumping to real code
u8 magic[8]; // ="eGON.BT0" or "eGON.BT1", not C-style string.
u32 check_sum; // generated by PC
u32 length; // generated by PC
u32 pub_head_size; // the size of boot_file_head_t
u8 pub_head_vsn[4]; // the version of boot_file_head_t
u8 file_head_vsn[4]; // the version of boot0_file_head_t or boot1_file_head_t
u8 Boot_vsn[4]; // Boot version
u8 eGON_vsn[4]; // eGON version
u8 platform[8]; // platform information
} boot_file_head_t;
#define BOOT0_MAGIC "eGON.BT0"
#define STAMP_VALUE 0x5F0A6C39
#define ROUND_UP_TO_8(x) (((x) + 7) / 8 * 8)
/** encoding of the jump instruction to skip over the header */
#define BROM_FILE_HEAD_SIZE (ROUND_UP_TO_8(sizeof(struct boot_file_head)) & 0x00FFFFF) /* for some reasons, the entry point is aligned to 8 bytes */
#define BROM_FILE_HEAD_BIT_10_1 ((BROM_FILE_HEAD_SIZE & 0x7FE) >> 1)
#define BROM_FILE_HEAD_BIT_11 ((BROM_FILE_HEAD_SIZE & 0x800) >> 11)
#define BROM_FILE_HEAD_BIT_19_12 ((BROM_FILE_HEAD_SIZE & 0xFF000) >> 12)
#define BROM_FILE_HEAD_BIT_20 ((BROM_FILE_HEAD_SIZE & 0x100000) >> 20)
#define BROM_FILE_HEAD_SIZE_OFFSET \
((BROM_FILE_HEAD_BIT_20 << 31) | \
(BROM_FILE_HEAD_BIT_10_1 << 21) | \
(BROM_FILE_HEAD_BIT_11 << 20) | \
(BROM_FILE_HEAD_BIT_19_12 << 12))
#define JUMP_INSTRUCTION (BROM_FILE_HEAD_SIZE_OFFSET | 0x6f)
/* check sum functon from sun4i boot code */
int gen_check_sum( void *boot_buf )
{
boot_file_head_t *head_p;
u32 length;
u32 *buf;
u32 loop;
u32 i;
u32 sum;
head_p = (boot_file_head_t *)boot_buf;
length = head_p->length;
if( ( length & 0x3 ) != 0 ) // must 4-byte-aligned
return -1;
buf = (u32 *)boot_buf;
head_p->check_sum = STAMP_VALUE; // fill stamp
loop = length >> 2;
/* calculate the sum */
for( i = 0, sum = 0; i < loop; i++ )
sum += buf[i];
/* write back check sum */
head_p->check_sum = sum;
return 0;
}
#define ALIGN(x,a) __ALIGN_MASK((x),(typeof(x))(a)-1)
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
#define SUN4I_SRAM_SIZE (24 * 1024)
#define SRAM_LOAD_MAX_SIZE (SUN4I_SRAM_SIZE - sizeof(boot_file_head_t))
#define BLOCK_SIZE 512
struct __attribute__((packed)) boot_img {
boot_file_head_t 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;
unsigned file_size, load_size;
int count;
if(argc < 2) {
printf("\tThis program makes an input bin file to sun4i bootable image.\n"
"\tUsage: %s input_file out_putfile\n", argv[0]);
return EXIT_FAILURE;
}
fd_in = open(argv[1], O_RDONLY);
if(fd_in < 0) {
perror("Open input file:");
return EXIT_FAILURE;
}
fd_out = open(argv[2], O_WRONLY|O_CREAT, 0666);
if(fd_out < 0) {
perror("Open output file:");
return EXIT_FAILURE;
}
memset((void *)img.pad, 0, BLOCK_SIZE);
/* get input file size */
file_size = lseek(fd_in, 0, SEEK_END);
printf("File size: 0x%x \n", file_size);
if(file_size > SRAM_LOAD_MAX_SIZE) {
load_size = SRAM_LOAD_MAX_SIZE;
} else {
load_size = ALIGN(file_size, sizeof(int));
}
printf("Load size: 0x%x \n", load_size);
/* read file to buffer to calculate checksum */
lseek(fd_in, 0, SEEK_SET);
count = read(fd_in, img.code, load_size);
printf("Read 0x%x bytes\n", count);
/* fill the header */
/* jump to the first instruction after the header */
img.header.jump_instruction = JUMP_INSTRUCTION;
memcpy(img.header.magic, BOOT0_MAGIC, 8); /* no '0' termination */
img.header.length = ALIGN(load_size + sizeof(boot_file_head_t), BLOCK_SIZE);
img.header.pub_head_size = sizeof(boot_file_head_t);
gen_check_sum((void *)&img);
count = write(fd_out, (void *)&img, img.header.length);
printf("Write 0x%x bytes\n", count);
close(fd_in);
close(fd_out);
return EXIT_SUCCESS;
}