4 * Copyright (C) 2016 Rafał Miłecki <zajec5@gmail.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
22 #if !defined(__BYTE_ORDER)
23 #error "Unknown byte order"
26 #if __BYTE_ORDER == __BIG_ENDIAN
27 #define cpu_to_be32(x) (x)
28 #define be32_to_cpu(x) (x)
29 #define cpu_to_be16(x) (x)
30 #define be16_to_cpu(x) (x)
31 #elif __BYTE_ORDER == __LITTLE_ENDIAN
32 #define cpu_to_be32(x) bswap_32(x)
33 #define be32_to_cpu(x) bswap_32(x)
34 #define cpu_to_be16(x) bswap_16(x)
35 #define be16_to_cpu(x) bswap_16(x)
37 #error "Unsupported endianness"
40 struct safeloader_header
{
43 } __attribute__ ((packed
));
45 char *safeloader_path
;
49 static inline size_t osafeloader_min(size_t x
, size_t y
) {
53 static const uint8_t md5_salt
[16] = {
54 0x7a, 0x2b, 0x15, 0xed,
55 0x9b, 0x98, 0x59, 0x6d,
56 0xe5, 0x04, 0xab, 0x44,
57 0xac, 0x2a, 0x9f, 0x4e,
60 /**************************************************
62 **************************************************/
64 static int osafeloader_info(int argc
, char **argv
) {
66 struct safeloader_header hdr
;
68 size_t bytes
, imagesize
;
76 fprintf(stderr
, "No SafeLoader file passed\n");
80 safeloader_path
= argv
[2];
82 safeloader
= fopen(safeloader_path
, "r");
84 fprintf(stderr
, "Couldn't open %s\n", safeloader_path
);
89 bytes
= fread(&hdr
, 1, sizeof(hdr
), safeloader
);
90 if (bytes
!= sizeof(hdr
)) {
91 fprintf(stderr
, "Couldn't read %s header\n", safeloader_path
);
95 imagesize
= be32_to_cpu(hdr
.imagesize
);
98 MD5_Update(&ctx
, md5_salt
, sizeof(md5_salt
));
99 while ((bytes
= fread(buf
, 1, osafeloader_min(sizeof(buf
), imagesize
), safeloader
)) > 0) {
100 MD5_Update(&ctx
, buf
, bytes
);
103 MD5_Final(md5
, &ctx
);
105 if (memcmp(md5
, hdr
.md5
, 16)) {
106 fprintf(stderr
, "Broken SafeLoader file with invalid MD5\n");
111 printf("%10s: %d\n", "Image size", be32_to_cpu(hdr
.imagesize
));
112 printf("%10s: ", "MD5");
113 for (i
= 0; i
< 16; i
++)
114 printf("%02x", md5
[i
]);
117 /* Skip header & vendor info */
118 fseek(safeloader
, 0x1014, SEEK_SET
);
120 while (fscanf(safeloader
, "fwup-ptn %s base 0x%x size 0x%x\t\r\n", name
, &base
, &size
) == 3) {
121 printf("%10s: %s (0x%x - 0x%x)\n", "Partition", name
, base
, base
+ size
);
130 /**************************************************
132 **************************************************/
134 static void osafeloader_extract_parse_options(int argc
, char **argv
) {
137 while ((c
= getopt(argc
, argv
, "p:o:")) != -1) {
140 partition_name
= optarg
;
149 static int osafeloader_extract(int argc
, char **argv
) {
152 struct safeloader_header hdr
;
159 fprintf(stderr
, "No SafeLoader file passed\n");
163 safeloader_path
= argv
[2];
166 osafeloader_extract_parse_options(argc
, argv
);
167 if (!partition_name
) {
168 fprintf(stderr
, "No partition name specified\n");
171 } else if (!out_path
) {
172 fprintf(stderr
, "No output file specified\n");
177 safeloader
= fopen(safeloader_path
, "r");
179 fprintf(stderr
, "Couldn't open %s\n", safeloader_path
);
184 out
= fopen(out_path
, "w");
186 fprintf(stderr
, "Couldn't open %s\n", out_path
);
188 goto err_close_safeloader
;
191 bytes
= fread(&hdr
, 1, sizeof(hdr
), safeloader
);
192 if (bytes
!= sizeof(hdr
)) {
193 fprintf(stderr
, "Couldn't read %s header\n", safeloader_path
);
198 /* Skip vendor info */
199 fseek(safeloader
, 0x1000, SEEK_CUR
);
202 while (fscanf(safeloader
, "fwup-ptn %s base 0x%x size 0x%x\t\r\n", name
, &base
, &size
) == 3) {
205 if (strcmp(name
, partition_name
))
210 fseek(safeloader
, sizeof(hdr
) + 0x1000 + base
, SEEK_SET
);
212 while ((bytes
= fread(buf
, 1, osafeloader_min(sizeof(buf
), size
), safeloader
)) > 0) {
213 if (fwrite(buf
, 1, bytes
, out
) != bytes
) {
214 fprintf(stderr
, "Couldn't write %zu B to %s\n", bytes
, out_path
);
222 fprintf(stderr
, "Couldn't extract whole partition %s from %s (%d B left)\n", partition_name
, safeloader_path
, size
);
231 err_close_safeloader
:
237 /**************************************************
239 **************************************************/
241 static void usage() {
244 printf("Info about SafeLoader:\n");
245 printf("\tosafeloader info <file>\n");
247 printf("Extract from SafeLoader:\n");
248 printf("\tosafeloader extract <file> [options]\n");
249 printf("\t-p name\t\t\t\tname of partition to extract\n");
250 printf("\t-o file\t\t\t\toutput file\n");
253 int main(int argc
, char **argv
) {
255 if (!strcmp(argv
[1], "info"))
256 return osafeloader_info(argc
, argv
);
257 else if (!strcmp(argv
[1], "extract"))
258 return osafeloader_extract(argc
, argv
);