loader.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Copyright (C) 2008 by Thermotemp GmbH. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THERMOTEMP GMBH AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THERMOTEMP
  21. * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  22. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  23. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. */
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include <stdlib.h>
  35. #include <sys/atom.h>
  36. #include <sys/timer.h>
  37. #include <sys/heap.h>
  38. #include <dev/nvmem.h>
  39. #include <arpa/inet.h>
  40. #include <arch/arm/atmel/at91_efc.h>
  41. #include <gorp/md5.h>
  42. #include "default.h"
  43. #include "debug.h"
  44. #include "loader.h"
  45. #include "tftp.h"
  46. #define IMAGE_OFFSET 0x0000C000
  47. #define IMAGE_START_ADDR 0x0010C000
  48. #define IMAGE_START "0x0010C000"
  49. /* Boot info structure. */
  50. CONFBOOT confboot;
  51. /* Read boot configuration from non-volatile memory. */
  52. static int read_boot_config(void)
  53. {
  54. int rc;
  55. rc = NutNvMemLoad(EE_CONFBOOT, &confboot, sizeof(CONFBOOT));
  56. if (confboot.cb_size != sizeof(CONFBOOT)) {
  57. rc = -1;
  58. }
  59. return rc;
  60. }
  61. /* Store boot configuration in non-volatile memory. */
  62. static void write_boot_config(void)
  63. {
  64. confboot.cb_size = sizeof(CONFBOOT);
  65. NutNvMemSave(EE_CONFBOOT, &confboot, sizeof(CONFBOOT));
  66. }
  67. /* Set default values for boot config */
  68. static void init_boot_config(void)
  69. {
  70. confboot.cb_size = sizeof (CONFBOOT);
  71. confboot.cb_flags = 0;
  72. confboot.cb_tftp_ip = inet_addr(DEFAULT_TFTP_SERVER);
  73. strcpy((char*)confboot.cb_image, DEFAULT_TFTP_IMAGE);
  74. memset(confboot.digest, 0, sizeof(confboot.digest));
  75. confboot.size = 0;
  76. }
  77. RAMFUNC void boot(void)
  78. {
  79. NutEnterCritical();
  80. /* Set all interrupts to be treated */
  81. outr(AIC_EOICR, 0);
  82. /* Disable _all_ interrupts */
  83. outr(AIC_IDCR, 0xFFFFFFFF);
  84. /* Disable clock to all devices */
  85. outr(PMC_PCDR, 0xFFFFFFFF);
  86. asm volatile ("@ Start Application" "\n\t"
  87. "ldr r0, =" IMAGE_START "\n\t"
  88. "bx r0" "\n\t"
  89. :::"r0"
  90. );
  91. }
  92. static int flasher_callback(u_char *buffer, u_short block_size, u_long offset, void* user_data)
  93. {
  94. int pos;
  95. int size;
  96. int rc;
  97. pos = 0;
  98. size = block_size;
  99. do {
  100. rc = -1;
  101. /* Write back new data. Maintain region lock. */
  102. if (At91EfcRegionUnlock(IMAGE_OFFSET + offset + pos) == 0) {
  103. size = MIN(FLASH_SECTOR_SIZE, block_size - pos);
  104. rc = At91EfcSectorWrite(IMAGE_OFFSET + offset + pos, &buffer[pos], size);
  105. At91EfcRegionLock(IMAGE_OFFSET + offset + pos);
  106. }
  107. if (rc == 0) {
  108. pos += size;
  109. } else {
  110. return -1;
  111. }
  112. } while ((int)block_size - pos > 0);
  113. return 0;
  114. }
  115. int check_or_save_md5(int size, int save)
  116. {
  117. MD5CONTEXT md5_ctx;
  118. u_char digest[16];
  119. int idx;
  120. int ok = 0;
  121. NutMD5Init(&md5_ctx);
  122. NutMD5Update(&md5_ctx, (u_char *)(IMAGE_START_ADDR), size);
  123. NutMD5Final(&md5_ctx, digest);
  124. if (save) {
  125. #if ((DEBUG_LEVEL) >= (LEVEL_INFO))
  126. INFO("MD5: ");
  127. for (idx = 0; idx < 16; idx++) {
  128. INFO("%02x", digest[idx]);
  129. }
  130. INFO("\r\n");
  131. #endif
  132. memcpy(confboot.digest, digest, sizeof(confboot.digest));
  133. confboot.size = size;
  134. write_boot_config();
  135. } else {
  136. for (idx = 0; idx < sizeof(digest); idx ++) {
  137. if (digest[idx] != confboot.digest[idx]) {
  138. ok = -1;
  139. break;
  140. }
  141. }
  142. #if ((DEBUG_LEVEL) >= (LEVEL_INFO))
  143. if (ok != 0) {
  144. INFO("MD5: ");
  145. for (idx = 0; idx < 16; idx++) {
  146. INFO("%02x", digest[idx]);
  147. }
  148. INFO("\r\n");
  149. INFO("Saved MD5: ");
  150. for (idx = 0; idx < 16; idx++) {
  151. INFO("%02x", confboot.digest[idx]);
  152. }
  153. INFO("\r\n");
  154. }
  155. #endif
  156. }
  157. return ok;
  158. }
  159. void loader(FILE *uart)
  160. {
  161. int size = 0;
  162. int loaded = FALSE;
  163. int retry = 3;
  164. while (!loaded) {
  165. if (confboot.cb_tftp_ip != 0) {
  166. size = tftp_receive(confboot.cb_image, confboot.cb_tftp_ip, flasher_callback, NULL);
  167. if (size < 0) {
  168. ERROR("TFTP error loading file %s from %s\r\n", confboot.cb_image, inet_ntoa(confboot.cb_tftp_ip));
  169. } else {
  170. check_or_save_md5(size, TRUE);
  171. loaded = TRUE;
  172. }
  173. } else {
  174. WARN("TFTP boot skipped. No tftp server configured\r\n");
  175. loaded = TRUE;
  176. }
  177. NutSleep(1000);
  178. retry--;
  179. if(!retry)
  180. break;
  181. }
  182. }
  183. void init_loader(void)
  184. {
  185. if (read_boot_config() != 0) {
  186. init_boot_config();
  187. write_boot_config();
  188. }
  189. }