• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/firmware-utils/src/bcm4908kernel.c

  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