1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2021 Rafał Miłecki <rafal@milecki.pl> 4 */ 5 6 #include <byteswap.h> 7 #include <endian.h> 8 #include <errno.h> 9 #include <stdint.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <unistd.h> 14 15 #if !defined(__BYTE_ORDER) 16 #error "Unknown byte order" 17 #endif 18 19 #if __BYTE_ORDER == __BIG_ENDIAN 20 #define cpu_to_le32(x) bswap_32(x) 21 #define le32_to_cpu(x) bswap_32(x) 22 #elif __BYTE_ORDER == __LITTLE_ENDIAN 23 #define cpu_to_le32(x) (x) 24 #define le32_to_cpu(x) (x) 25 #else 26 #error "Unsupported endianness" 27 #endif 28 29 struct bcm4908kernel_header { 30 uint32_t boot_load_addr; /* AKA la_address */ 31 uint32_t boot_addr; /* AKA la_entrypt */ 32 uint32_t data_len; 33 uint8_t magic[4]; 34 uint32_t uncomplen; /* Empty for LZMA, used for LZ4 */ 35 }; 36 37 static void usage() { 38 printf("Usage:\n"); 39 printf("\n"); 40 printf("\t-i pathname\t\t\tinput kernel filepath\n"); 41 printf("\t-o pathname\t\t\toutput kernel filepath\n"); 42 } 43 44 int main(int argc, char **argv) { 45 struct bcm4908kernel_header header; 46 uint8_t buf[1024]; 47 FILE *out = NULL; 48 FILE *in = NULL; 49 size_t length; 50 size_t bytes; 51 int err = 0; 52 char c; 53 54 if (argc >= 2 && !strcmp(argv[1], "-h")) { 55 usage(); 56 return 0; 57 } 58 59 while ((c = getopt(argc, argv, "i:o:")) != -1) { 60 switch (c) { 61 case 'i': 62 in = fopen(optarg, "r"); 63 break; 64 case 'o': 65 out = fopen(optarg, "w+"); 66 break; 67 } 68 } 69 70 if (!in || !out) { 71 fprintf(stderr, "Failed to open input and/or output file\n"); 72 usage(); 73 return -EINVAL; 74 } 75 76 if (fread(&header, 1, sizeof(header), in) != sizeof(header)) { 77 fprintf(stderr, "Failed to read %zu bytes from input file\n", sizeof(header)); 78 err = -EIO; 79 goto err_close; 80 } 81 82 if (!memcmp(header.magic, "BRCM", 4)) { 83 fprintf(stderr, "Input file already contains BCM4908 kernel header\n"); 84 err = -EIO; 85 goto err_close; 86 } 87 88 err = fseek(out, sizeof(header), SEEK_SET); 89 if (err) { 90 err = -errno; 91 fprintf(stderr, "Failed to fseek(): %d\n", err); 92 goto err_close; 93 } 94 95 length = 0; 96 rewind(in); 97 while ((bytes = fread(buf, 1, sizeof(buf), in)) > 0) { 98 if (fwrite(buf, 1, bytes, out) != bytes) { 99 fprintf(stderr, "Failed to write %zu B to the output file\n", bytes); 100 err = -EIO; 101 goto err_close; 102 } 103 length += bytes; 104 } 105 106 header.boot_load_addr = cpu_to_le32(0x00080000); 107 header.boot_addr = cpu_to_le32(0x00080000); 108 header.data_len = cpu_to_le32(length); 109 header.magic[0] = 'B'; 110 header.magic[1] = 'R'; 111 header.magic[2] = 'C'; 112 header.magic[3] = 'M'; 113 header.uncomplen = 0; 114 115 fseek(out, 0, SEEK_SET); 116 117 if (fwrite(&header, 1, sizeof(header), out) != sizeof(header)) { 118 fprintf(stderr, "Failed to write header to the output file\n"); 119 err = -EIO; 120 goto err_close; 121 } 122 123 err_close: 124 fclose(out); 125 fclose(in); 126 return err; 127 } 128
This page was automatically generated by LXR 0.3.1. • OpenWrt