bcm4908kernel.c 2.6 KB

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