scp.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /*
  2. * Copyright (c) 2017 - 2020, Broadcom
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <string.h>
  7. #include <arch_helpers.h>
  8. #include <common/debug.h>
  9. /* MCU binary image structure: <header> <data>
  10. *
  11. * Header structure:
  12. * <magic-start>
  13. * <num-sections>
  14. * {<src-offset> <src-size> <dst-addr>}*
  15. * <magic-end>
  16. *
  17. * MCU data (<data>) consists of several sections of code/data, to be
  18. * installed (copied) into MCU memories.
  19. * Header (<header>) gives information about sections contained in <data>.
  20. *
  21. * The installer code iterates over sections in MCU binary.
  22. * For each section, it copies the section into MCU memory.
  23. *
  24. * The header contains:
  25. * - <magic-start> - 32-bit magic number to mark header start
  26. * - <num-sections> - number of sections in <data>
  27. * - <num-sections> tuples. Each tuple describes a section.
  28. * A tuple contains three 32-bit words.
  29. * - <magic-end> - 32-bit magic number to mark header end
  30. *
  31. * Each section is describes by a tuple, consisting of three 32-bit words:
  32. * - offset of section within MCU binary (relative to beginning of <data>)
  33. * - section size (in bytes) in MCU binary
  34. * - target address (in MCU memory). Section is copied to this location.
  35. *
  36. * All fields are 32-bit unsigned integers in little endian format.
  37. * All sizes are assumed to be 32-bit aligned.
  38. */
  39. #define SCP_BIN_HEADER_MAGIC_START 0xfa587D01
  40. #define SCP_BIN_HEADER_MAGIC_END 0xf3e06a85
  41. int download_scp_patch(void *image, unsigned int image_size)
  42. {
  43. unsigned int *pheader = (unsigned int *)(image);
  44. unsigned int header_size;
  45. unsigned char *pdata;
  46. void *dest;
  47. unsigned int num_sections;
  48. unsigned int section_src_offset;
  49. unsigned int section_size;
  50. if (pheader && (pheader[0] != SCP_BIN_HEADER_MAGIC_START)) {
  51. ERROR("SCP: Could not find SCP header.\n");
  52. return -1;
  53. }
  54. num_sections = pheader[1];
  55. INFO("...Number of sections: %d\n", num_sections);
  56. header_size = 4 * (1 + 1 + 3 * num_sections + 1);
  57. if (image_size < header_size) {
  58. ERROR("SCP: Wrong size.\n");
  59. return -1;
  60. }
  61. if (*(pheader + header_size/4 - 1) != SCP_BIN_HEADER_MAGIC_END) {
  62. ERROR("SCP: Could not find SCP footer.\n");
  63. return -1;
  64. }
  65. VERBOSE("SCP image header validated successfully\n");
  66. pdata = (unsigned char *)pheader + header_size;
  67. for (pheader += 2; num_sections > 0; num_sections--) {
  68. section_src_offset = pheader[0];
  69. section_size = pheader[1];
  70. dest = (void *)(unsigned long)pheader[2];
  71. INFO("section: src:0x%x, size:%d, dst:0x%x\n",
  72. section_src_offset, section_size, pheader[2]);
  73. if ((section_src_offset + section_size) > image_size) {
  74. ERROR("SCP: Section points to outside of patch.\n");
  75. return -1;
  76. }
  77. /* copy from source to target section */
  78. memcpy(dest, pdata + section_src_offset, section_size);
  79. flush_dcache_range((uintptr_t)dest, section_size);
  80. /* next section */
  81. pheader += 3;
  82. }
  83. return 0;
  84. }