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);