blob: f75226f3751651431b620c5c4d717ebe6d61294e [file] [log] [blame]
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* FIXME: this code is absolutely atrocious and needs to be re-written
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
#include <uuid/uuid.h>
#include "mosys/log.h"
#include "lib/math.h"
#include "lib/string.h"
#include "lib/vpd.h"
#include "lib/vpd_tables.h"
#include "lib_vpd_encode.h"
#include "symbol.h"
/**
* vpd_append_type0 - append type 0 (firmware info) structure to a buffer
*
* @handle: handle for this structure
* @buf: buffer to append to
* @len: length of buffer
* @vendor: firmware vendor (string)
* @version: firmware version (string)
* @start: offset of firmware runtime code in ROM image
* @date: firmware release date (string)
* @rom_size: ROM size (in 64KB blocks)
* @major_ver: firmware major version
* @minor_ver: firmware minor version
* @ec_major_ver: EC firmware major version
* @ec_minor_ver: EC firmware minor version
*
* returns total size of newly re-sized buffer if successful
* returns <0 to indicate failure
*/
int vpd_append_type0(uint16_t handle, uint8_t **buf, size_t len,
char *vendor, char *version, uint16_t start, char *date,
uint8_t rom_size, uint8_t major_ver, uint8_t minor_ver,
uint8_t ec_major_ver, uint8_t ec_minor_ver)
{
struct vpd_header *header;
struct vpd_table_firmware *data;
uint8_t *strings, *p;
size_t struct_len, total_len;
/* FIXME: Add sanity checking */
struct_len = sizeof(struct vpd_header) +
sizeof(struct vpd_table_firmware) +
strlen(vendor) + 1 +
strlen(version) + 1 +
strlen(date) + 1 +
1; /* structure terminator */
total_len = len + struct_len;
*buf = realloc(*buf, total_len);
memset(*buf + len, 0, struct_len);
p = *buf + len;
header = (struct vpd_header *)p;
p += sizeof(*header);
data = (struct vpd_table_firmware *)p;
p += sizeof(*data);
strings = p;
/* fill in structure header details */
header->type = VPD_TYPE_FIRMWARE;
header->length = sizeof(*header) + sizeof(*data);
header->handle = handle;
data->vendor = 1;
data->version = 2;
data->start_address = start,
data->rom_size_64k_blocks = rom_size - 1;
data->major_ver = major_ver;
data->minor_ver = minor_ver;
data->ec_major_ver = ec_major_ver;
data->ec_minor_ver = ec_minor_ver;
data->release_date = 3;
sprintf(strings, "%s%c%s%c%s%c",
vendor, '\0',
version, '\0',
date, '\0');
memset(&buf[struct_len], 0, 1); /* terminator */
lprintf(LOG_DEBUG, "%s: total length (including strings): %u\n",
__func__, (unsigned)total_len);
print_buf(LOG_DEBUG, data, total_len);
return total_len;
}
/**
* sym2type0 - extract symbols and append firmware info table to buffer
*
* @handle: handle for this structure
* @buf: buffer to append to
* @len: length of buffer
*
* This function is intended to hide tedious symbol extraction steps from
* higher-level logic.
*
* returns total size of newly re-sized buffer if successful
* returns <0 to indicate failure
*/
int sym2type0(uint16_t handle, uint8_t **buf, size_t len)
{
char *vendor, *version, *release_date;
uint16_t start;
uint8_t rom_size, major_ver, minor_ver, ec_major_ver, ec_minor_ver;
char *tmp;
errno = 0;
vendor = version = release_date = NULL;
/* strings */
if (!(vendor = sym2str("CONFIG_FIRMWARE_VENDOR"))) return -1;
if (!(version = sym2str("CONFIG_FIRMWARE_VERSION"))) return -1;
if (!(release_date = sym2str("CONFIG_FIRMWARE_RELEASE_DATE"))) return -1;
/* optional values */
tmp = sym2str("CONFIG_FIRMWARE_START");
if (tmp) {
start = (uint16_t)strtoul(tmp, NULL, 0);
if (errno) return -1;
} else {
/* set default value */
start = 0;
}
/* required values */
if (!(tmp = sym2str("CONFIG_FIRMWARE_ROM_SIZE"))) return -1;
rom_size = (uint8_t)strtoul(tmp, NULL, 0);
if (errno) return -1;
if (!(tmp = sym2str("CONFIG_SYSTEM_FIRMWARE_MAJOR_RELEASE"))) return -1;
major_ver = (uint8_t)strtoul(tmp, NULL, 0);
if (errno) return -1;
if (!(tmp = sym2str("CONFIG_SYSTEM_FIRMWARE_MINOR_RELEASE"))) return -1;
minor_ver = (uint8_t)strtoul(tmp, NULL, 0);
if (errno) return -1;
if (!(tmp = sym2str("CONFIG_EC_FIRMWARE_MAJOR_RELEASE"))) return -1;
ec_major_ver = (uint8_t)strtoul(tmp, NULL, 0);
if (errno) return -1;
if (!(tmp = sym2str("CONFIG_EC_FIRMWARE_MINOR_RELEASE"))) return -1;
lprintf(LOG_INFO, "checkpoint 7\n");
ec_minor_ver = (uint8_t)strtoul(tmp, NULL, 0);
lprintf(LOG_INFO, "checkpoint 8\n");
if (errno) return -1;
return vpd_append_type0(handle, buf, len, vendor, version, start,
release_date, rom_size, major_ver, minor_ver,
ec_major_ver, ec_minor_ver);
}