1527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 2527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass * Use of this source code is governed by a BSD-style license that can be 3527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass * found in the LICENSE file. 4527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass * 5527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass * High-level firmware API for loading and verifying rewritable firmware. 6527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass * (Firmware portion) 7527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass */ 8527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 9527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass#include "sysincludes.h" 10527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 11527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass#include "bmpblk_header.h" 12527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass#include "region.h" 13527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass#include "gbb_access.h" 14527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass#include "gbb_header.h" 15527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass#include "load_kernel_fw.h" 16527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass#include "utility.h" 17527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass#include "vboot_api.h" 18527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass#include "vboot_struct.h" 19527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 20527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glassstatic VbError_t VbRegionReadGbb(VbCommonParams *cparams, uint32_t offset, 21527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass uint32_t size, void *buf) 22527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass{ 23527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return VbRegionReadData(cparams, VB_REGION_GBB, offset, size, buf); 24527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass} 25527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 26527ba810eff4006cf69579f6b96cb4350cb1e189Simon GlassVbError_t VbGbbReadBmpHeader(VbCommonParams *cparams, BmpBlockHeader *hdr_ret) 27527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass{ 28527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass BmpBlockHeader *hdr; 29527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass VbError_t ret; 30527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 31527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (!cparams) 32527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return VBERROR_INVALID_GBB; 33527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (!cparams->bmp) { 34527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass GoogleBinaryBlockHeader *gbb = cparams->gbb; 35527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 36527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (0 == gbb->bmpfv_size) 37527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return VBERROR_INVALID_GBB; 38527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 39527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass hdr = VbExMalloc(sizeof(*hdr)); 40527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass ret = VbRegionReadGbb(cparams, gbb->bmpfv_offset, 41527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass sizeof(BmpBlockHeader), hdr); 42527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (ret) { 43527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass VbExFree(hdr); 44527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return ret; 45527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass } 46527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 47527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass /* Sanity-check the bitmap block header */ 48527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if ((0 != Memcmp(hdr->signature, BMPBLOCK_SIGNATURE, 49527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass BMPBLOCK_SIGNATURE_SIZE)) || 50527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass (hdr->major_version > BMPBLOCK_MAJOR_VERSION) || 51527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass ((hdr->major_version == BMPBLOCK_MAJOR_VERSION) && 52527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass (hdr->minor_version > BMPBLOCK_MINOR_VERSION))) { 53527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass VBDEBUG(("VbDisplayScreenFromGBB(): " 54527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass "invalid/too new bitmap header\n")); 55527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass VbExFree(hdr); 56527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return VBERROR_INVALID_BMPFV; 57527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass } 58527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass cparams->bmp = hdr; 59527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass } 60527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 61527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass *hdr_ret = *cparams->bmp; 62527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return VBERROR_SUCCESS; 63527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass} 64527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 65527ba810eff4006cf69579f6b96cb4350cb1e189Simon GlassVbError_t VbRegionReadHWID(VbCommonParams *cparams, char *hwid, 66527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass uint32_t max_size) 67527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass{ 68527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass GoogleBinaryBlockHeader *gbb; 69527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass VbError_t ret; 70527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 71527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (!max_size) 72527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return VBERROR_INVALID_PARAMETER; 73527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass *hwid = '\0'; 74527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass StrnAppend(hwid, "{INVALID}", max_size); 75527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (!cparams) 76527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return VBERROR_INVALID_GBB; 77527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 78527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass gbb = cparams->gbb; 79527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 80527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (0 == gbb->hwid_size) { 81527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass VBDEBUG(("VbHWID(): invalid hwid size\n")); 82527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return VBERROR_SUCCESS; /* oddly enough! */ 83527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass } 84527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 85527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (gbb->hwid_size > max_size) { 86527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass VBDEBUG(("VbDisplayDebugInfo(): invalid hwid offset/size\n")); 87527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return VBERROR_INVALID_PARAMETER; 88527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass } 89527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass ret = VbRegionReadGbb(cparams, gbb->hwid_offset, gbb->hwid_size, hwid); 90527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (ret) 91527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return ret; 92527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 93527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return VBERROR_SUCCESS; 94527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass} 95527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 96527ba810eff4006cf69579f6b96cb4350cb1e189Simon GlassVbError_t VbGbbReadImage(VbCommonParams *cparams, 97527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass uint32_t localization, uint32_t screen_index, 98527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass uint32_t image_num, ScreenLayout *layout, 99527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass ImageInfo *image_info, char **image_datap, 100527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass uint32_t *image_data_sizep) 101527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass{ 102527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass uint32_t layout_offset, image_offset, data_offset, data_size; 103527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass GoogleBinaryBlockHeader *gbb; 104527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass BmpBlockHeader hdr; 105527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass void *data = NULL; 106527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass VbError_t ret; 107527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 108527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (!cparams) 109527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return VBERROR_INVALID_GBB; 110527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 111527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass ret = VbGbbReadBmpHeader(cparams, &hdr); 112527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (ret) 113527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return ret; 114527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 115527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass gbb = cparams->gbb; 116527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass layout_offset = gbb->bmpfv_offset + sizeof(BmpBlockHeader) + 117527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass localization * hdr.number_of_screenlayouts * 118527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass sizeof(ScreenLayout) + 119527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass screen_index * sizeof(ScreenLayout); 120527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass ret = VbRegionReadGbb(cparams, layout_offset, sizeof(*layout), layout); 121527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (ret) 122527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return ret; 123527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 124527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (!layout->images[image_num].image_info_offset) 125527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return VBERROR_NO_IMAGE_PRESENT; 126527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 127527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass image_offset = gbb->bmpfv_offset + 128527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass layout->images[image_num].image_info_offset; 129527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass ret = VbRegionReadGbb(cparams, image_offset, sizeof(*image_info), 130527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass image_info); 131527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (ret) 132527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return ret; 133527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 134527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass data_offset = image_offset + sizeof(*image_info); 135527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass data_size = image_info->compressed_size; 136527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (data_size) { 137527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass void *orig_data; 138527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 139527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass data = VbExMalloc(image_info->compressed_size); 140527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass ret = VbRegionReadGbb(cparams, data_offset, 141527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass image_info->compressed_size, data); 142527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (ret) { 143527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass VbExFree(data); 144527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return ret; 145527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass } 146527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (image_info->compression != COMPRESS_NONE) { 147527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass uint32_t inoutsize = image_info->original_size; 148527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 149527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass orig_data = VbExMalloc(image_info->original_size); 150527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass ret = VbExDecompress(data, 151527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass image_info->compressed_size, 152527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass image_info->compression, 153527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass orig_data, &inoutsize); 154527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass data_size = inoutsize; 155527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass VbExFree(data); 156527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass data = orig_data; 157527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (ret) { 158527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass VbExFree(data); 159527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return ret; 160527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass } 161527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass } 162527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass } 163527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 164527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass *image_datap = data; 165527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass *image_data_sizep = data_size; 166527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 167527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return VBERROR_SUCCESS; 168527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass} 169527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 170527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass#define OUTBUF_LEN 128 171527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 172527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glassvoid VbRegionCheckVersion(VbCommonParams *cparams) 173527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass{ 174527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass GoogleBinaryBlockHeader *gbb; 175527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 176527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (!cparams) 177527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass return; 178527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 179527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass gbb = cparams->gbb; 180527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 181527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass /* 182527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass * If GBB flags is nonzero, complain because that's something that the 183527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass * factory MUST fix before shipping. We only have to do this here, 184527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass * because it's obvious that something is wrong if we're not displaying 185527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass * screens from the GBB. 186527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass */ 187527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass if (gbb->major_version == GBB_MAJOR_VER && gbb->minor_version >= 1 && 188527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass (gbb->flags != 0)) { 189527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass uint32_t used = 0; 190527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass char outbuf[OUTBUF_LEN]; 191527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass 192527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass *outbuf = '\0'; 193527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass used += StrnAppend(outbuf + used, "gbb.flags is nonzero: 0x", 194527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass OUTBUF_LEN - used); 195527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass used += Uint64ToString(outbuf + used, OUTBUF_LEN - used, 196527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass gbb->flags, 16, 8); 197527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass used += StrnAppend(outbuf + used, "\n", OUTBUF_LEN - used); 198527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass (void)VbExDisplayDebugInfo(outbuf); 199527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass } 200527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass} 201