diff options
Diffstat (limited to 'arch/ppc/boot/utils/mkbugboot.c')
-rw-r--r-- | arch/ppc/boot/utils/mkbugboot.c | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/arch/ppc/boot/utils/mkbugboot.c b/arch/ppc/boot/utils/mkbugboot.c new file mode 100644 index 000000000000..886122283f39 --- /dev/null +++ b/arch/ppc/boot/utils/mkbugboot.c | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | * arch/ppc/boot/utils/mkbugboot.c | ||
3 | * | ||
4 | * Makes a Motorola PPCBUG ROM bootable image which can be flashed | ||
5 | * into one of the FLASH banks on a Motorola PowerPlus board. | ||
6 | * | ||
7 | * Author: Matt Porter <mporter@mvista.com> | ||
8 | * | ||
9 | * 2001 (c) MontaVista, Software, Inc. This file is licensed under | ||
10 | * the terms of the GNU General Public License version 2. This program | ||
11 | * is licensed "as is" without any warranty of any kind, whether express | ||
12 | * or implied. | ||
13 | */ | ||
14 | |||
15 | #define ELF_HEADER_SIZE 65536 | ||
16 | |||
17 | #include <unistd.h> | ||
18 | #include <sys/stat.h> | ||
19 | #include <string.h> | ||
20 | #include <stdio.h> | ||
21 | #include <stdlib.h> | ||
22 | #include <errno.h> | ||
23 | #include <fcntl.h> | ||
24 | #ifdef __sun__ | ||
25 | #include <inttypes.h> | ||
26 | #else | ||
27 | #include <stdint.h> | ||
28 | #endif | ||
29 | |||
30 | #ifdef __i386__ | ||
31 | #define cpu_to_be32(x) le32_to_cpu(x) | ||
32 | #define cpu_to_be16(x) le16_to_cpu(x) | ||
33 | #else | ||
34 | #define cpu_to_be32(x) (x) | ||
35 | #define cpu_to_be16(x) (x) | ||
36 | #endif | ||
37 | |||
38 | #define cpu_to_le32(x) le32_to_cpu((x)) | ||
39 | unsigned long le32_to_cpu(unsigned long x) | ||
40 | { | ||
41 | return (((x & 0x000000ffU) << 24) | | ||
42 | ((x & 0x0000ff00U) << 8) | | ||
43 | ((x & 0x00ff0000U) >> 8) | | ||
44 | ((x & 0xff000000U) >> 24)); | ||
45 | } | ||
46 | |||
47 | #define cpu_to_le16(x) le16_to_cpu((x)) | ||
48 | unsigned short le16_to_cpu(unsigned short x) | ||
49 | { | ||
50 | return (((x & 0x00ff) << 8) | | ||
51 | ((x & 0xff00) >> 8)); | ||
52 | } | ||
53 | |||
54 | /* size of read buffer */ | ||
55 | #define SIZE 0x1000 | ||
56 | |||
57 | /* PPCBUG ROM boot header */ | ||
58 | typedef struct bug_boot_header { | ||
59 | uint8_t magic_word[4]; /* "BOOT" */ | ||
60 | uint32_t entry_offset; /* Offset from top of header to code */ | ||
61 | uint32_t routine_length; /* Length of code */ | ||
62 | uint8_t routine_name[8]; /* Name of the boot code */ | ||
63 | } bug_boot_header_t; | ||
64 | |||
65 | #define HEADER_SIZE sizeof(bug_boot_header_t) | ||
66 | |||
67 | uint32_t copy_image(int32_t in_fd, int32_t out_fd) | ||
68 | { | ||
69 | uint8_t buf[SIZE]; | ||
70 | int n; | ||
71 | uint32_t image_size = 0; | ||
72 | uint8_t zero = 0; | ||
73 | |||
74 | lseek(in_fd, ELF_HEADER_SIZE, SEEK_SET); | ||
75 | |||
76 | /* Copy an image while recording its size */ | ||
77 | while ( (n = read(in_fd, buf, SIZE)) > 0 ) | ||
78 | { | ||
79 | image_size = image_size + n; | ||
80 | write(out_fd, buf, n); | ||
81 | } | ||
82 | |||
83 | /* BUG romboot requires that our size is divisible by 2 */ | ||
84 | /* align image to 2 byte boundary */ | ||
85 | if (image_size % 2) | ||
86 | { | ||
87 | image_size++; | ||
88 | write(out_fd, &zero, 1); | ||
89 | } | ||
90 | |||
91 | return image_size; | ||
92 | } | ||
93 | |||
94 | void write_bugboot_header(int32_t out_fd, uint32_t boot_size) | ||
95 | { | ||
96 | uint8_t header_block[HEADER_SIZE]; | ||
97 | bug_boot_header_t *bbh = (bug_boot_header_t *)&header_block[0]; | ||
98 | |||
99 | memset(header_block, 0, HEADER_SIZE); | ||
100 | |||
101 | /* Fill in the PPCBUG ROM boot header */ | ||
102 | strncpy(bbh->magic_word, "BOOT", 4); /* PPCBUG magic word */ | ||
103 | bbh->entry_offset = cpu_to_be32(HEADER_SIZE); /* Entry address */ | ||
104 | bbh->routine_length= cpu_to_be32(HEADER_SIZE+boot_size+2); /* Routine length */ | ||
105 | strncpy(bbh->routine_name, "LINUXROM", 8); /* Routine name */ | ||
106 | |||
107 | /* Output the header and bootloader to the file */ | ||
108 | write(out_fd, header_block, HEADER_SIZE); | ||
109 | } | ||
110 | |||
111 | uint16_t calc_checksum(int32_t bug_fd) | ||
112 | { | ||
113 | uint32_t checksum_var = 0; | ||
114 | uint8_t buf[2]; | ||
115 | int n; | ||
116 | |||
117 | /* Checksum loop */ | ||
118 | while ( (n = read(bug_fd, buf, 2) ) ) | ||
119 | { | ||
120 | checksum_var = checksum_var + *(uint16_t *)buf; | ||
121 | |||
122 | /* If we carry out, mask it and add one to the checksum */ | ||
123 | if (checksum_var >> 16) | ||
124 | checksum_var = (checksum_var & 0x0000ffff) + 1; | ||
125 | } | ||
126 | |||
127 | return checksum_var; | ||
128 | } | ||
129 | |||
130 | int main(int argc, char *argv[]) | ||
131 | { | ||
132 | int32_t image_fd, bugboot_fd; | ||
133 | int argptr = 1; | ||
134 | uint32_t kernel_size = 0; | ||
135 | uint16_t checksum = 0; | ||
136 | uint8_t bugbootname[256]; | ||
137 | |||
138 | if ( (argc != 3) ) | ||
139 | { | ||
140 | fprintf(stderr, "usage: %s <kernel_image> <bugboot>\n",argv[0]); | ||
141 | exit(-1); | ||
142 | } | ||
143 | |||
144 | /* Get file args */ | ||
145 | |||
146 | /* kernel image file */ | ||
147 | if ((image_fd = open( argv[argptr] , 0)) < 0) | ||
148 | exit(-1); | ||
149 | argptr++; | ||
150 | |||
151 | /* bugboot file */ | ||
152 | if ( !strcmp( argv[argptr], "-" ) ) | ||
153 | bugboot_fd = 1; /* stdout */ | ||
154 | else | ||
155 | if ((bugboot_fd = creat( argv[argptr] , 0755)) < 0) | ||
156 | exit(-1); | ||
157 | else | ||
158 | strcpy(bugbootname, argv[argptr]); | ||
159 | argptr++; | ||
160 | |||
161 | /* Set file position after ROM header block where zImage will be written */ | ||
162 | lseek(bugboot_fd, HEADER_SIZE, SEEK_SET); | ||
163 | |||
164 | /* Copy kernel image into bugboot image */ | ||
165 | kernel_size = copy_image(image_fd, bugboot_fd); | ||
166 | close(image_fd); | ||
167 | |||
168 | /* Set file position to beginning where header/romboot will be written */ | ||
169 | lseek(bugboot_fd, 0, SEEK_SET); | ||
170 | |||
171 | /* Write out BUG header/romboot */ | ||
172 | write_bugboot_header(bugboot_fd, kernel_size); | ||
173 | |||
174 | /* Close bugboot file */ | ||
175 | close(bugboot_fd); | ||
176 | |||
177 | /* Reopen it as read/write */ | ||
178 | bugboot_fd = open(bugbootname, O_RDWR); | ||
179 | |||
180 | /* Calculate checksum */ | ||
181 | checksum = calc_checksum(bugboot_fd); | ||
182 | |||
183 | /* Write out the calculated checksum */ | ||
184 | write(bugboot_fd, &checksum, 2); | ||
185 | |||
186 | return 0; | ||
187 | } | ||