region-kernel.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
  2. * Use of this source code is governed by a BSD-style license that can be
  3. * found in the LICENSE file.
  4. *
  5. * High-level firmware API for loading and verifying rewritable firmware.
  6. * (Firmware portion)
  7. */
  8. #include "2sysincludes.h"
  9. #include "2common.h"
  10. #include "sysincludes.h"
  11. #include "bmpblk_header.h"
  12. #include "region.h"
  13. #include "gbb_access.h"
  14. #include "gbb_header.h"
  15. #include "load_kernel_fw.h"
  16. #include "utility.h"
  17. #include "vboot_api.h"
  18. #include "vboot_struct.h"
  19. static VbError_t VbRegionReadGbb(VbCommonParams *cparams, uint32_t offset,
  20. uint32_t size, void *buf)
  21. {
  22. return VbRegionReadData(cparams, VB_REGION_GBB, offset, size, buf);
  23. }
  24. VbError_t VbGbbReadBmpHeader(VbCommonParams *cparams, BmpBlockHeader *hdr_ret)
  25. {
  26. BmpBlockHeader *hdr;
  27. VbError_t ret;
  28. if (!cparams)
  29. return VBERROR_INVALID_GBB;
  30. if (!cparams->bmp) {
  31. GoogleBinaryBlockHeader *gbb = cparams->gbb;
  32. if (0 == gbb->bmpfv_size)
  33. return VBERROR_INVALID_GBB;
  34. hdr = malloc(sizeof(*hdr));
  35. ret = VbRegionReadGbb(cparams, gbb->bmpfv_offset,
  36. sizeof(BmpBlockHeader), hdr);
  37. if (ret) {
  38. free(hdr);
  39. return ret;
  40. }
  41. /* Sanity-check the bitmap block header */
  42. if ((0 != memcmp(hdr->signature, BMPBLOCK_SIGNATURE,
  43. BMPBLOCK_SIGNATURE_SIZE)) ||
  44. (hdr->major_version > BMPBLOCK_MAJOR_VERSION) ||
  45. ((hdr->major_version == BMPBLOCK_MAJOR_VERSION) &&
  46. (hdr->minor_version > BMPBLOCK_MINOR_VERSION))) {
  47. VB2_DEBUG("VbGbbReadBmpHeader(): "
  48. "invalid/too new bitmap header\n");
  49. free(hdr);
  50. return VBERROR_INVALID_BMPFV;
  51. }
  52. cparams->bmp = hdr;
  53. }
  54. *hdr_ret = *cparams->bmp;
  55. return VBERROR_SUCCESS;
  56. }
  57. VbError_t VbRegionReadHWID(VbCommonParams *cparams, char *hwid,
  58. uint32_t max_size)
  59. {
  60. GoogleBinaryBlockHeader *gbb;
  61. VbError_t ret;
  62. if (!max_size)
  63. return VBERROR_INVALID_PARAMETER;
  64. *hwid = '\0';
  65. StrnAppend(hwid, "{INVALID}", max_size);
  66. if (!cparams)
  67. return VBERROR_INVALID_GBB;
  68. gbb = cparams->gbb;
  69. if (0 == gbb->hwid_size) {
  70. VB2_DEBUG("VbHWID(): invalid hwid size\n");
  71. return VBERROR_SUCCESS; /* oddly enough! */
  72. }
  73. if (gbb->hwid_size > max_size) {
  74. VB2_DEBUG("VbDisplayDebugInfo(): invalid hwid offset/size\n");
  75. return VBERROR_INVALID_PARAMETER;
  76. }
  77. ret = VbRegionReadGbb(cparams, gbb->hwid_offset, gbb->hwid_size, hwid);
  78. if (ret)
  79. return ret;
  80. return VBERROR_SUCCESS;
  81. }
  82. VbError_t VbGbbReadImage(VbCommonParams *cparams,
  83. uint32_t localization, uint32_t screen_index,
  84. uint32_t image_num, ScreenLayout *layout,
  85. ImageInfo *image_info, char **image_datap,
  86. uint32_t *image_data_sizep)
  87. {
  88. uint32_t layout_offset, image_offset, data_offset, data_size;
  89. GoogleBinaryBlockHeader *gbb;
  90. BmpBlockHeader hdr;
  91. void *data = NULL;
  92. VbError_t ret;
  93. if (!cparams)
  94. return VBERROR_INVALID_GBB;
  95. ret = VbGbbReadBmpHeader(cparams, &hdr);
  96. if (ret)
  97. return ret;
  98. gbb = cparams->gbb;
  99. layout_offset = gbb->bmpfv_offset + sizeof(BmpBlockHeader) +
  100. localization * hdr.number_of_screenlayouts *
  101. sizeof(ScreenLayout) +
  102. screen_index * sizeof(ScreenLayout);
  103. ret = VbRegionReadGbb(cparams, layout_offset, sizeof(*layout), layout);
  104. if (ret)
  105. return ret;
  106. if (!layout->images[image_num].image_info_offset)
  107. return VBERROR_NO_IMAGE_PRESENT;
  108. image_offset = gbb->bmpfv_offset +
  109. layout->images[image_num].image_info_offset;
  110. ret = VbRegionReadGbb(cparams, image_offset, sizeof(*image_info),
  111. image_info);
  112. if (ret)
  113. return ret;
  114. data_offset = image_offset + sizeof(*image_info);
  115. data_size = image_info->compressed_size;
  116. if (data_size) {
  117. void *orig_data;
  118. data = malloc(image_info->compressed_size);
  119. ret = VbRegionReadGbb(cparams, data_offset,
  120. image_info->compressed_size, data);
  121. if (ret) {
  122. free(data);
  123. return ret;
  124. }
  125. if (image_info->compression != COMPRESS_NONE) {
  126. uint32_t inoutsize = image_info->original_size;
  127. orig_data = malloc(image_info->original_size);
  128. ret = VbExDecompress(data,
  129. image_info->compressed_size,
  130. image_info->compression,
  131. orig_data, &inoutsize);
  132. data_size = inoutsize;
  133. free(data);
  134. data = orig_data;
  135. if (ret) {
  136. free(data);
  137. return ret;
  138. }
  139. }
  140. }
  141. *image_datap = data;
  142. *image_data_sizep = data_size;
  143. return VBERROR_SUCCESS;
  144. }
  145. #define OUTBUF_LEN 128
  146. void VbRegionCheckVersion(VbCommonParams *cparams)
  147. {
  148. GoogleBinaryBlockHeader *gbb;
  149. if (!cparams)
  150. return;
  151. gbb = cparams->gbb;
  152. /*
  153. * If GBB flags is nonzero, complain because that's something that the
  154. * factory MUST fix before shipping. We only have to do this here,
  155. * because it's obvious that something is wrong if we're not displaying
  156. * screens from the GBB.
  157. */
  158. if (gbb->major_version == GBB_MAJOR_VER && gbb->minor_version >= 1 &&
  159. (gbb->flags != 0)) {
  160. uint32_t used = 0;
  161. char outbuf[OUTBUF_LEN];
  162. *outbuf = '\0';
  163. used += StrnAppend(outbuf + used, "gbb.flags is nonzero: 0x",
  164. OUTBUF_LEN - used);
  165. used += Uint64ToString(outbuf + used, OUTBUF_LEN - used,
  166. gbb->flags, 16, 8);
  167. used += StrnAppend(outbuf + used, "\n", OUTBUF_LEN - used);
  168. (void)VbExDisplayDebugInfo(outbuf);
  169. }
  170. }