| /* |
| * Copyright (c) 2011 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. |
| * |
| * Alternatively, this software may be distributed under the terms of the |
| * GNU General Public License ("GPL") version 2 as published by the Free |
| * Software Foundation. |
| */ |
| |
| #include <common.h> |
| #include <cros/common.h> |
| #include <cros/gbb.h> |
| |
| #include <gbb_header.h> |
| static uint32_t gbb_flags; |
| |
| int gbb_init(read_buf_type gbb, firmware_storage_t *file, uint32_t gbb_offset, |
| size_t gbb_size) |
| { |
| #ifndef CONFIG_HARDWARE_MAPPED_SPI |
| GoogleBinaryBlockHeader *gbbh = (GoogleBinaryBlockHeader *)gbb; |
| uint32_t hwid_end; |
| uint32_t rootkey_end; |
| |
| if (file->read(file, gbb_offset, sizeof(*gbbh), gbbh)) { |
| VBDEBUG("failed to read GBB header\n"); |
| return 1; |
| } |
| |
| hwid_end = gbbh->hwid_offset + gbbh->hwid_size; |
| rootkey_end = gbbh->rootkey_offset + gbbh->rootkey_size; |
| if (hwid_end < gbbh->hwid_offset || hwid_end > gbb_size || |
| rootkey_end < gbbh->rootkey_offset || |
| rootkey_end > gbb_size) { |
| VBDEBUG("%s: invalid gbb header entries\n", __func__); |
| VBDEBUG(" hwid_end=%x\n", hwid_end); |
| VBDEBUG(" gbbh->hwid_offset=%x\n", gbbh->hwid_offset); |
| VBDEBUG(" gbb_size=%x\n", gbb_size); |
| VBDEBUG(" rootkey_end=%x\n", rootkey_end); |
| VBDEBUG(" gbbh->rootkey_offset=%x\n", |
| gbbh->rootkey_offset); |
| VBDEBUG(" %d, %d, %d, %d\n", |
| hwid_end < gbbh->hwid_offset, |
| hwid_end >= gbb_size, |
| rootkey_end < gbbh->rootkey_offset, |
| rootkey_end >= gbb_size); |
| return 1; |
| } |
| |
| if (file->read(file, gbb_offset + gbbh->hwid_offset, |
| gbbh->hwid_size, |
| gbb + gbbh->hwid_offset)) { |
| VBDEBUG("failed to read hwid\n"); |
| return 1; |
| } |
| |
| if (file->read(file, gbb_offset + gbbh->rootkey_offset, |
| gbbh->rootkey_size, |
| gbb + gbbh->rootkey_offset)) { |
| VBDEBUG("failed to read root key\n"); |
| return 1; |
| } |
| gbb_flags = gbbh->flags; |
| #else |
| /* No data is actually moved in this case so no bounds checks. */ |
| if (file->read(file, gbb_offset, |
| sizeof(GoogleBinaryBlockHeader), gbb)) { |
| VBDEBUG("failed to read GBB header\n"); |
| return 1; |
| } |
| gbb_flags = ((GoogleBinaryBlockHeader *)gbb)->flags; |
| #endif |
| |
| return 0; |
| } |
| |
| #ifndef CONFIG_HARDWARE_MAPPED_SPI |
| int gbb_read_bmp_block(void *gbb, firmware_storage_t *file, uint32_t gbb_offset, |
| size_t gbb_size) |
| { |
| GoogleBinaryBlockHeader *gbbh = (GoogleBinaryBlockHeader *)gbb; |
| uint32_t bmpfv_end = gbbh->bmpfv_offset + gbbh->bmpfv_size; |
| |
| if (bmpfv_end < gbbh->bmpfv_offset || bmpfv_end > gbb_size) { |
| VBDEBUG("%s: invalid gbb header entries\n", __func__); |
| return 1; |
| } |
| |
| if (file->read(file, gbb_offset + gbbh->bmpfv_offset, |
| gbbh->bmpfv_size, |
| gbb + gbbh->bmpfv_offset)) { |
| VBDEBUG("failed to read bmp block\n"); |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| int gbb_read_recovery_key(void *gbb, firmware_storage_t *file, |
| uint32_t gbb_offset, size_t gbb_size) |
| { |
| GoogleBinaryBlockHeader *gbbh = (GoogleBinaryBlockHeader *)gbb; |
| uint32_t rkey_end = gbbh->recovery_key_offset + |
| gbbh->recovery_key_size; |
| |
| if (rkey_end < gbbh->recovery_key_offset || rkey_end > gbb_size) { |
| VBDEBUG("%s: invalid gbb header entries\n", __func__); |
| VBDEBUG(" gbbh->recovery_key_offset=%x\n", |
| gbbh->recovery_key_offset); |
| VBDEBUG(" gbbh->recovery_key_size=%x\n", |
| gbbh->recovery_key_size); |
| VBDEBUG(" rkey_end=%x\n", rkey_end); |
| VBDEBUG(" gbb_size=%x\n", gbb_size); |
| return 1; |
| } |
| |
| if (file->read(file, gbb_offset + gbbh->recovery_key_offset, |
| gbbh->recovery_key_size, |
| gbb + gbbh->recovery_key_offset)) { |
| VBDEBUG("failed to read recovery key\n"); |
| return 1; |
| } |
| |
| return 0; |
| } |
| #endif |
| |
| uint32_t gbb_get_flags(void) |
| { |
| return gbb_flags; |
| } |
| |
| int gbb_check_integrity(uint8_t *gbb) |
| { |
| /* |
| * Avoid a second "$GBB" signature in the binary. Some utility programs |
| * that parses the contents of firmware image could fail if there are |
| * multiple signatures. |
| */ |
| if (gbb[0] == '$' && gbb[1] == 'G' && gbb[2] == 'B' && gbb[3] == 'B') |
| return 0; |
| else |
| return 1; |
| } |