rs232-loader.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * rs232-loader - load elf file over RS232 console port
  3. *
  4. * Copyright (c) 2009 Openmoko Inc.
  5. *
  6. * Authors Daniel Mack <daniel@caiaq.de>
  7. * Marek Lindner <marek@openmoko.com>
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. */
  22. // Note: This will need changes to MBR baud rate or the load time will
  23. // be very long
  24. // Try 115200 or 57600 and keep the interface connection very short
  25. #define APPLICATION_TITLE "rs232 loader"
  26. #include "application.h"
  27. #include <string.h>
  28. #define ET_EXEC 2
  29. #define EM_C33 0x6b
  30. #define ELFMAG0 0x7f
  31. #define ELFMAG1 0x45
  32. #define ELFMAG2 0x4c
  33. #define ELFMAG3 0x46
  34. typedef struct {
  35. uint8_t e_ident[16]; // ELF "magic number"
  36. uint16_t e_type; // Identifies object file type
  37. uint16_t e_machine; // Specifies required architecture
  38. uint32_t e_version; // Identifies object file version
  39. uint32_t e_entry; // Entry point virtual address
  40. uint32_t e_phoff; // Program header table file offset
  41. uint32_t e_shoff; // Section header table file offset
  42. uint32_t e_flags; // Processor-specific flags
  43. uint16_t e_ehsize; // ELF header size in bytes
  44. uint16_t e_phentsize; // Program header table entry size
  45. uint16_t e_phnum; // Program header table entry count
  46. uint16_t e_shentsize; // Section header table entry size
  47. uint16_t e_shnum; // Section header table entry count
  48. uint16_t e_shstrndx; // Section header string table index
  49. } __attribute__((packed)) elf32_hdr;
  50. typedef struct {
  51. uint32_t sh_name; // Section name, index in string tbl
  52. uint32_t sh_type; // Type of section
  53. uint32_t sh_flags; // Miscellaneous section attributes
  54. uint32_t sh_addr; // Section virtual addr at execution
  55. uint32_t sh_offset; // Section file offset
  56. uint32_t sh_size; // Size of section in bytes
  57. uint32_t sh_link; // Index of another section
  58. uint32_t sh_info; // Additional section information
  59. uint32_t sh_addralign; // Section alignment
  60. uint32_t sh_entsize; // Entry size if section holds table
  61. } __attribute__((packed)) elf32_sec;
  62. #define SHT_NULL 0 // Section header table entry unused
  63. #define SHT_PROGBITS 1 // Program specific (private) data
  64. #define SHT_SYMTAB 2 // Link editing symbol table
  65. #define SHT_STRTAB 3 // A string table
  66. #define SHT_RELA 4 // Relocation entries with addends
  67. #define SHT_HASH 5 // A symbol hash table
  68. #define SHT_DYNAMIC 6 // Information for dynamic linking
  69. #define SHT_NOTE 7 // Information that marks file
  70. #define SHT_NOBITS 8 // Section occupies no space in file
  71. #define SHT_REL 9 // Relocation entries, no addends
  72. #define SHT_SHLIB 10 // Reserved, unspecified semantics
  73. #define SHT_DYNSYM 11 // Dynamic linking symbol table
  74. #define BUFFER (uint8_t *)(0x10000000 + 16 * 1024 * 1024)
  75. void rs232_elf_load(void);
  76. // this must be the first executable code as the loader executes from the first program address
  77. ReturnType rs232_loader(int block, int status)
  78. {
  79. APPLICATION_INITIALISE();
  80. rs232_elf_load();
  81. APPLICATION_FINALISE(0, 0);
  82. }
  83. void rs232_elf_load(void)
  84. {
  85. uint32_t file_size;
  86. elf32_hdr *hdr;
  87. unsigned int i;
  88. void *exec;
  89. elf32_sec *sec;
  90. print("Waiting for file from the serial line ... \n");
  91. for (i = 0; i < sizeof(uint32_t); i++) {
  92. ((unsigned char *)&file_size)[i] = console_input_char();
  93. }
  94. for (i = 0; i < file_size; i++) {
  95. (BUFFER)[i] = console_input_char();
  96. }
  97. hdr = (elf32_hdr *)BUFFER;
  98. if (hdr->e_ident[0] != ELFMAG0 ||
  99. hdr->e_ident[1] != ELFMAG1 ||
  100. hdr->e_ident[2] != ELFMAG2 ||
  101. hdr->e_ident[3] != ELFMAG3) {
  102. print("invalid ELF magic\n");
  103. return;
  104. }
  105. if (hdr->e_type != ET_EXEC) {
  106. print("invalid ELF file type\n");
  107. return;
  108. }
  109. if (hdr->e_machine != EM_C33) {
  110. print("FAIL: machine\n");
  111. return;
  112. }
  113. for (i = 0; i < hdr->e_shnum; i++) {
  114. sec = (elf32_sec *)(BUFFER + (hdr->e_shoff + (sizeof(elf32_sec) * i)));
  115. switch (sec->sh_type) {
  116. case SHT_PROGBITS:
  117. memcpy((uint8_t *)sec->sh_addr, BUFFER + sec->sh_offset, sec->sh_size);
  118. print("PROG: ");
  119. print_hex(sec->sh_addr);
  120. print_char('\n');
  121. break;
  122. case SHT_NOBITS:
  123. // clean .bss sections
  124. memset((uint8_t *)sec->sh_addr, 0, sec->sh_size);
  125. break;
  126. default:
  127. break;
  128. }
  129. }
  130. print("EXEC from serial: ");
  131. print_hex(hdr->e_entry);
  132. print_char('\n');
  133. exec = (void *)hdr->e_entry;
  134. ((void (*) (void))exec) ();
  135. }