mkbugboot.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * Makes a Motorola PPCBUG ROM bootable image which can be flashed
  3. * into one of the FLASH banks on a Motorola PowerPlus board.
  4. *
  5. * Author: Matt Porter <mporter@mvista.com>
  6. *
  7. * 2001 (c) MontaVista, Software, Inc. This file is licensed under
  8. * the terms of the GNU General Public License version 2. This program
  9. * is licensed "as is" without any warranty of any kind, whether express
  10. * or implied.
  11. */
  12. #define ELF_HEADER_SIZE 65536
  13. #include <unistd.h>
  14. #include <sys/stat.h>
  15. #include <string.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <errno.h>
  19. #include <fcntl.h>
  20. #ifdef __sun__
  21. #include <inttypes.h>
  22. #else
  23. #include <stdint.h>
  24. #endif
  25. #ifdef __i386__
  26. #define cpu_to_be32(x) le32_to_cpu(x)
  27. #define cpu_to_be16(x) le16_to_cpu(x)
  28. #else
  29. #define cpu_to_be32(x) (x)
  30. #define cpu_to_be16(x) (x)
  31. #endif
  32. #define cpu_to_le32(x) le32_to_cpu((x))
  33. unsigned long le32_to_cpu(unsigned long x)
  34. {
  35. return (((x & 0x000000ffU) << 24) |
  36. ((x & 0x0000ff00U) << 8) |
  37. ((x & 0x00ff0000U) >> 8) |
  38. ((x & 0xff000000U) >> 24));
  39. }
  40. #define cpu_to_le16(x) le16_to_cpu((x))
  41. unsigned short le16_to_cpu(unsigned short x)
  42. {
  43. return (((x & 0x00ff) << 8) |
  44. ((x & 0xff00) >> 8));
  45. }
  46. /* size of read buffer */
  47. #define SIZE 0x1000
  48. /* PPCBUG ROM boot header */
  49. typedef struct bug_boot_header {
  50. uint8_t magic_word[4]; /* "BOOT" */
  51. uint32_t entry_offset; /* Offset from top of header to code */
  52. uint32_t routine_length; /* Length of code */
  53. uint8_t routine_name[8]; /* Name of the boot code */
  54. } bug_boot_header_t;
  55. #define HEADER_SIZE sizeof(bug_boot_header_t)
  56. uint32_t copy_image(int32_t in_fd, int32_t out_fd)
  57. {
  58. uint8_t buf[SIZE];
  59. int n;
  60. uint32_t image_size = 0;
  61. uint8_t zero = 0;
  62. lseek(in_fd, ELF_HEADER_SIZE, SEEK_SET);
  63. /* Copy an image while recording its size */
  64. while ( (n = read(in_fd, buf, SIZE)) > 0 )
  65. {
  66. image_size = image_size + n;
  67. write(out_fd, buf, n);
  68. }
  69. /* BUG romboot requires that our size is divisible by 2 */
  70. /* align image to 2 byte boundary */
  71. if (image_size % 2)
  72. {
  73. image_size++;
  74. write(out_fd, &zero, 1);
  75. }
  76. return image_size;
  77. }
  78. void write_bugboot_header(int32_t out_fd, uint32_t boot_size)
  79. {
  80. uint8_t header_block[HEADER_SIZE];
  81. bug_boot_header_t *bbh = (bug_boot_header_t *)&header_block[0];
  82. memset(header_block, 0, HEADER_SIZE);
  83. /* Fill in the PPCBUG ROM boot header */
  84. strncpy(bbh->magic_word, "BOOT", 4); /* PPCBUG magic word */
  85. bbh->entry_offset = cpu_to_be32(HEADER_SIZE); /* Entry address */
  86. bbh->routine_length= cpu_to_be32(HEADER_SIZE+boot_size+2); /* Routine length */
  87. strncpy(bbh->routine_name, "LINUXROM", 8); /* Routine name */
  88. /* Output the header and bootloader to the file */
  89. write(out_fd, header_block, HEADER_SIZE);
  90. }
  91. uint16_t calc_checksum(int32_t bug_fd)
  92. {
  93. uint32_t checksum_var = 0;
  94. uint8_t buf[2];
  95. int n;
  96. /* Checksum loop */
  97. while ( (n = read(bug_fd, buf, 2) ) )
  98. {
  99. checksum_var = checksum_var + *(uint16_t *)buf;
  100. /* If we carry out, mask it and add one to the checksum */
  101. if (checksum_var >> 16)
  102. checksum_var = (checksum_var & 0x0000ffff) + 1;
  103. }
  104. return checksum_var;
  105. }
  106. int main(int argc, char *argv[])
  107. {
  108. int32_t image_fd, bugboot_fd;
  109. int argptr = 1;
  110. uint32_t kernel_size = 0;
  111. uint16_t checksum = 0;
  112. uint8_t bugbootname[256];
  113. if ( (argc != 3) )
  114. {
  115. fprintf(stderr, "usage: %s <kernel_image> <bugboot>\n",argv[0]);
  116. exit(-1);
  117. }
  118. /* Get file args */
  119. /* kernel image file */
  120. if ((image_fd = open( argv[argptr] , 0)) < 0)
  121. exit(-1);
  122. argptr++;
  123. /* bugboot file */
  124. if ( !strcmp( argv[argptr], "-" ) )
  125. bugboot_fd = 1; /* stdout */
  126. else
  127. if ((bugboot_fd = creat( argv[argptr] , 0755)) < 0)
  128. exit(-1);
  129. else
  130. strcpy(bugbootname, argv[argptr]);
  131. argptr++;
  132. /* Set file position after ROM header block where zImage will be written */
  133. lseek(bugboot_fd, HEADER_SIZE, SEEK_SET);
  134. /* Copy kernel image into bugboot image */
  135. kernel_size = copy_image(image_fd, bugboot_fd);
  136. close(image_fd);
  137. /* Set file position to beginning where header/romboot will be written */
  138. lseek(bugboot_fd, 0, SEEK_SET);
  139. /* Write out BUG header/romboot */
  140. write_bugboot_header(bugboot_fd, kernel_size);
  141. /* Close bugboot file */
  142. close(bugboot_fd);
  143. /* Reopen it as read/write */
  144. bugboot_fd = open(bugbootname, O_RDWR);
  145. /* Calculate checksum */
  146. checksum = calc_checksum(bugboot_fd);
  147. /* Write out the calculated checksum */
  148. write(bugboot_fd, &checksum, 2);
  149. return 0;
  150. }