Files
OpenCellular/firmware/lib/region-kernel.c
Randall Spangler 559a110f33 vboot: use malloc and free directly
Originally, vboot1 code used VbExMalloc() and VbExFree() since it needed
to talk to EFI firmware that didn't have standard malloc() and free().
Now, coreboot and depthcharge implement them as wrappers around those
standard calls.  vboot2 code already calls them directly, so let vboot1
code do that too.

BUG=chromium:611535
BRANCH=none
TEST=make runtests; emerge-kevin coreboot depthcharge

Change-Id: I49ad0e32e38d278dc3589bfaf494bcf0e4b0a4bd
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/400905
2016-11-06 02:33:50 +00:00

201 lines
5.0 KiB
C

/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* High-level firmware API for loading and verifying rewritable firmware.
* (Firmware portion)
*/
#include "sysincludes.h"
#include "bmpblk_header.h"
#include "region.h"
#include "gbb_access.h"
#include "gbb_header.h"
#include "load_kernel_fw.h"
#include "utility.h"
#include "vboot_api.h"
#include "vboot_struct.h"
static VbError_t VbRegionReadGbb(VbCommonParams *cparams, uint32_t offset,
uint32_t size, void *buf)
{
return VbRegionReadData(cparams, VB_REGION_GBB, offset, size, buf);
}
VbError_t VbGbbReadBmpHeader(VbCommonParams *cparams, BmpBlockHeader *hdr_ret)
{
BmpBlockHeader *hdr;
VbError_t ret;
if (!cparams)
return VBERROR_INVALID_GBB;
if (!cparams->bmp) {
GoogleBinaryBlockHeader *gbb = cparams->gbb;
if (0 == gbb->bmpfv_size)
return VBERROR_INVALID_GBB;
hdr = malloc(sizeof(*hdr));
ret = VbRegionReadGbb(cparams, gbb->bmpfv_offset,
sizeof(BmpBlockHeader), hdr);
if (ret) {
free(hdr);
return ret;
}
/* Sanity-check the bitmap block header */
if ((0 != memcmp(hdr->signature, BMPBLOCK_SIGNATURE,
BMPBLOCK_SIGNATURE_SIZE)) ||
(hdr->major_version > BMPBLOCK_MAJOR_VERSION) ||
((hdr->major_version == BMPBLOCK_MAJOR_VERSION) &&
(hdr->minor_version > BMPBLOCK_MINOR_VERSION))) {
VBDEBUG(("VbGbbReadBmpHeader(): "
"invalid/too new bitmap header\n"));
free(hdr);
return VBERROR_INVALID_BMPFV;
}
cparams->bmp = hdr;
}
*hdr_ret = *cparams->bmp;
return VBERROR_SUCCESS;
}
VbError_t VbRegionReadHWID(VbCommonParams *cparams, char *hwid,
uint32_t max_size)
{
GoogleBinaryBlockHeader *gbb;
VbError_t ret;
if (!max_size)
return VBERROR_INVALID_PARAMETER;
*hwid = '\0';
StrnAppend(hwid, "{INVALID}", max_size);
if (!cparams)
return VBERROR_INVALID_GBB;
gbb = cparams->gbb;
if (0 == gbb->hwid_size) {
VBDEBUG(("VbHWID(): invalid hwid size\n"));
return VBERROR_SUCCESS; /* oddly enough! */
}
if (gbb->hwid_size > max_size) {
VBDEBUG(("VbDisplayDebugInfo(): invalid hwid offset/size\n"));
return VBERROR_INVALID_PARAMETER;
}
ret = VbRegionReadGbb(cparams, gbb->hwid_offset, gbb->hwid_size, hwid);
if (ret)
return ret;
return VBERROR_SUCCESS;
}
VbError_t VbGbbReadImage(VbCommonParams *cparams,
uint32_t localization, uint32_t screen_index,
uint32_t image_num, ScreenLayout *layout,
ImageInfo *image_info, char **image_datap,
uint32_t *image_data_sizep)
{
uint32_t layout_offset, image_offset, data_offset, data_size;
GoogleBinaryBlockHeader *gbb;
BmpBlockHeader hdr;
void *data = NULL;
VbError_t ret;
if (!cparams)
return VBERROR_INVALID_GBB;
ret = VbGbbReadBmpHeader(cparams, &hdr);
if (ret)
return ret;
gbb = cparams->gbb;
layout_offset = gbb->bmpfv_offset + sizeof(BmpBlockHeader) +
localization * hdr.number_of_screenlayouts *
sizeof(ScreenLayout) +
screen_index * sizeof(ScreenLayout);
ret = VbRegionReadGbb(cparams, layout_offset, sizeof(*layout), layout);
if (ret)
return ret;
if (!layout->images[image_num].image_info_offset)
return VBERROR_NO_IMAGE_PRESENT;
image_offset = gbb->bmpfv_offset +
layout->images[image_num].image_info_offset;
ret = VbRegionReadGbb(cparams, image_offset, sizeof(*image_info),
image_info);
if (ret)
return ret;
data_offset = image_offset + sizeof(*image_info);
data_size = image_info->compressed_size;
if (data_size) {
void *orig_data;
data = malloc(image_info->compressed_size);
ret = VbRegionReadGbb(cparams, data_offset,
image_info->compressed_size, data);
if (ret) {
free(data);
return ret;
}
if (image_info->compression != COMPRESS_NONE) {
uint32_t inoutsize = image_info->original_size;
orig_data = malloc(image_info->original_size);
ret = VbExDecompress(data,
image_info->compressed_size,
image_info->compression,
orig_data, &inoutsize);
data_size = inoutsize;
free(data);
data = orig_data;
if (ret) {
free(data);
return ret;
}
}
}
*image_datap = data;
*image_data_sizep = data_size;
return VBERROR_SUCCESS;
}
#define OUTBUF_LEN 128
void VbRegionCheckVersion(VbCommonParams *cparams)
{
GoogleBinaryBlockHeader *gbb;
if (!cparams)
return;
gbb = cparams->gbb;
/*
* If GBB flags is nonzero, complain because that's something that the
* factory MUST fix before shipping. We only have to do this here,
* because it's obvious that something is wrong if we're not displaying
* screens from the GBB.
*/
if (gbb->major_version == GBB_MAJOR_VER && gbb->minor_version >= 1 &&
(gbb->flags != 0)) {
uint32_t used = 0;
char outbuf[OUTBUF_LEN];
*outbuf = '\0';
used += StrnAppend(outbuf + used, "gbb.flags is nonzero: 0x",
OUTBUF_LEN - used);
used += Uint64ToString(outbuf + used, OUTBUF_LEN - used,
gbb->flags, 16, 8);
used += StrnAppend(outbuf + used, "\n", OUTBUF_LEN - used);
(void)VbExDisplayDebugInfo(outbuf);
}
}