mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-09 00:51:29 +00:00
CBI: Add cbi-util
cbi-util is a build command line tool, which creates a blob containing board information. When invoked with '--show' option, it prints the information stored in a blob and validates the data. BUG=b:70294260 BRANCH=none TEST=Run the command as follows: $ cbi-util --create /path/to/cbi.bin \ --board_version 0xabcd --oem_id 2 --sku_id 3 --size 256 $ cbi-util --show /path/to/cbi.bin CBI blob: /path/to/cbi.bin BOARD_VERSION: 0.1 (0xab.cd) OEM_ID: 2 (0x02) SKU_ID: 3 (0x03) Data validated successfully $ cbi-util --create /path/to/cbi.bin \ --board_version 0xabcd --oem_id 2 --sku_id 3 Missing required arguments $ cbi-util --create /path/to/cbi.bin --board_version 0xabcde Invalid --board_version Change-Id: I7e7b439c50943523039c3cafda3bdf7d08962c61 Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/860961 Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
committed by
chrome-bot
parent
6e3e0f87b1
commit
c62060d9d9
@@ -57,6 +57,12 @@ $(out)/util/gen_touchpad_hash: BUILD_CFLAGS += $(OPENSSL_CFLAGS)
|
||||
$(out)/util/gen_touchpad_hash: BUILD_LDFLAGS += $(OPENSSL_LDFLAGS)
|
||||
endif # CONFIG_TOUCHPAD_VIRTUAL_OFF
|
||||
|
||||
build-util-bin += cbi-util
|
||||
$(out)/util/cbi-util: $(out)/util/crc8.o
|
||||
$(out)/util/cbi-util: BUILD_LDFLAGS=$(out)/util/crc8.o -static
|
||||
$(out)/util/crc8.o: common/crc8.c
|
||||
$(call quiet,c_to_vif,BUILDCC)
|
||||
|
||||
$(out)/util/export_taskinfo.so: $(out)/util/export_taskinfo_ro.o \
|
||||
$(out)/util/export_taskinfo_rw.o
|
||||
$(call quiet,link_taskinfo,BUILDLD)
|
||||
|
||||
338
util/cbi-util.c
Normal file
338
util/cbi-util.c
Normal file
@@ -0,0 +1,338 @@
|
||||
/* Copyright 2018 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.
|
||||
*
|
||||
* Cros Board Info utility
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "cros_board_info.h"
|
||||
#include "crc8.h"
|
||||
|
||||
#define REQUIRED_MASK_BOARD_VERSION (1 << 0)
|
||||
#define REQUIRED_MASK_OEM_ID (1 << 1)
|
||||
#define REQUIRED_MASK_SKU_ID (1 << 2)
|
||||
#define REQUIRED_MASK_SIZE (1 << 3)
|
||||
#define REQUIRED_MASK_FILENAME (1 << 4)
|
||||
#define REQUIRED_MASK_CREATE (REQUIRED_MASK_BOARD_VERSION | \
|
||||
REQUIRED_MASK_OEM_ID | \
|
||||
REQUIRED_MASK_SKU_ID | \
|
||||
REQUIRED_MASK_SIZE | \
|
||||
REQUIRED_MASK_FILENAME)
|
||||
#define REQUIRED_MASK_SHOW (REQUIRED_MASK_FILENAME)
|
||||
|
||||
/* Command line options */
|
||||
enum {
|
||||
/* mode options */
|
||||
OPT_MODE_NONE,
|
||||
OPT_MODE_CREATE,
|
||||
OPT_MODE_SHOW,
|
||||
OPT_BOARD_VERSION,
|
||||
OPT_OEM_ID,
|
||||
OPT_SKU_ID,
|
||||
OPT_SIZE,
|
||||
OPT_ERASE_BYTE,
|
||||
OPT_SHOW_ALL,
|
||||
OPT_HELP,
|
||||
};
|
||||
|
||||
static const struct option long_opts[] = {
|
||||
{"create", 1, 0, OPT_MODE_CREATE},
|
||||
{"show", 1, 0, OPT_MODE_SHOW},
|
||||
{"board_version", 1, 0, OPT_BOARD_VERSION},
|
||||
{"oem_id", 1, 0, OPT_OEM_ID},
|
||||
{"sku_id", 1, 0, OPT_SKU_ID},
|
||||
{"size", 1, 0, OPT_SIZE},
|
||||
{"erase_byte", 1, 0, OPT_ERASE_BYTE},
|
||||
{"all", 0, 0, OPT_SHOW_ALL},
|
||||
{"help", 0, 0, OPT_HELP},
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
static int write_file(const char *filename, const char *buf, int size)
|
||||
{
|
||||
FILE *f;
|
||||
int i;
|
||||
|
||||
/* Write to file */
|
||||
f = fopen(filename, "wb");
|
||||
if (!f) {
|
||||
perror("Error opening output file");
|
||||
return -1;
|
||||
}
|
||||
i = fwrite(buf, 1, size, f);
|
||||
fclose(f);
|
||||
if (i != size) {
|
||||
perror("Error writing to file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t *read_file(const char *filename, uint32_t *size_ptr)
|
||||
{
|
||||
FILE *f;
|
||||
uint8_t *buf;
|
||||
long size;
|
||||
|
||||
*size_ptr = 0;
|
||||
|
||||
f = fopen(filename, "rb");
|
||||
if (!f) {
|
||||
fprintf(stderr, "Unable to open file %s\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
size = ftell(f);
|
||||
rewind(f);
|
||||
|
||||
if (size < 0 || size > UINT32_MAX) {
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = malloc(size);
|
||||
if (!buf) {
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (1 != fread(buf, size, 1, f)) {
|
||||
fprintf(stderr, "Unable to read file %s\n", filename);
|
||||
fclose(f);
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
*size_ptr = size;
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int cbi_crc8(const struct board_info *bi)
|
||||
{
|
||||
return crc8((uint8_t *)&bi->head.crc + 1, bi->head.total_size - 4);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a CBI blob
|
||||
*/
|
||||
static int do_create(const char *cbi_filename, uint32_t size, uint8_t erase,
|
||||
struct board_info *bi)
|
||||
{
|
||||
int rv;
|
||||
uint8_t *buf;
|
||||
|
||||
buf = malloc(size);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Failed to allocate memory\n");
|
||||
return -1;
|
||||
}
|
||||
memset(buf, erase, size);
|
||||
|
||||
memcpy(bi->head.magic, cbi_magic, sizeof(bi->head.magic));
|
||||
bi->head.major_version = CBI_VERSION_MAJOR;
|
||||
bi->head.minor_version = CBI_VERSION_MINOR;
|
||||
bi->head.total_size = sizeof(*bi);
|
||||
bi->head.crc = cbi_crc8(bi);
|
||||
memcpy(buf, bi, sizeof(*bi));
|
||||
|
||||
/* Output blob */
|
||||
rv = write_file(cbi_filename, buf, size);
|
||||
if (rv) {
|
||||
fprintf(stderr, "Unable to write CBI blob\n");
|
||||
return rv;
|
||||
}
|
||||
|
||||
fprintf(stderr, "CBI blob is created successfully\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_show(const char *cbi_filename, int show_all)
|
||||
{
|
||||
uint8_t *buf;
|
||||
uint32_t size;
|
||||
struct board_info *bi;
|
||||
|
||||
if (!cbi_filename) {
|
||||
fprintf(stderr, "Missing arguments\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf = read_file(cbi_filename, &size);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Unable to read CBI blob\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bi = (struct board_info *)buf;
|
||||
printf("CBI blob: %s\n", cbi_filename);
|
||||
printf(" BOARD_VERSION: %d.%d (0x%02x.%02x)\n",
|
||||
bi->major_version, bi->minor_version,
|
||||
bi->major_version, bi->minor_version);
|
||||
printf(" OEM_ID: %d (0x%02x)\n", bi->oem_id, bi->oem_id);
|
||||
printf(" SKU_ID: %d (0x%02x)\n", bi->sku_id, bi->sku_id);
|
||||
|
||||
if (memcmp(bi->head.magic, cbi_magic, sizeof(cbi_magic))) {
|
||||
fprintf(stderr, "Invalid Magic\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cbi_crc8(bi) != bi->head.crc) {
|
||||
fprintf(stderr, "Invalid CRC\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Data validated successfully\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Print help and return error */
|
||||
static void print_help(int argc, char *argv[])
|
||||
{
|
||||
printf("\nUsage: cbi %s <--create|--show>\n"
|
||||
"\n"
|
||||
"Utility for managing Cros Board Info (CBIs).\n"
|
||||
"\n"
|
||||
"For '--create <cbi_file> [OPTIONS]', required OPTIONS are:\n"
|
||||
" --board_version <uint16> Board version\n"
|
||||
" --oem_id <uint8> OEM ID\n"
|
||||
" --sku_id <uint8> SKU ID\n"
|
||||
" --size <uint16> Size of output file\n"
|
||||
"Optional OPTIONS are:\n"
|
||||
" --erase_byte <uint8> Byte used for empty space\n"
|
||||
" --format_version <uint16> Data format version\n"
|
||||
"\n"
|
||||
"For '--show <cbi_file> [OPTIONS]', OPTIONS are:\n"
|
||||
" --all Dump all information\n"
|
||||
" It also validates the contents against the checksum and\n"
|
||||
" returns non-zero if validation fails.\n"
|
||||
"\n",
|
||||
argv[0]);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int mode = OPT_MODE_NONE;
|
||||
const char *cbi_filename = NULL;
|
||||
struct board_info bi;
|
||||
uint32_t size;
|
||||
uint8_t erase = 0xff;
|
||||
int show_all = 0;
|
||||
int parse_error = 0;
|
||||
uint32_t required_mask = 0;
|
||||
uint32_t set_mask = 0;
|
||||
uint64_t val;
|
||||
char *e;
|
||||
int i;
|
||||
|
||||
memset(&bi, 0, sizeof(bi));
|
||||
|
||||
while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
|
||||
switch (i) {
|
||||
case '?':
|
||||
/* Unhandled option */
|
||||
fprintf(stderr, "Unknown option or missing value\n");
|
||||
parse_error = 1;
|
||||
break;
|
||||
case OPT_HELP:
|
||||
print_help(argc, argv);
|
||||
return !!parse_error;
|
||||
case OPT_MODE_CREATE:
|
||||
mode = i;
|
||||
cbi_filename = optarg;
|
||||
required_mask = REQUIRED_MASK_CREATE;
|
||||
set_mask |= REQUIRED_MASK_FILENAME;
|
||||
break;
|
||||
case OPT_MODE_SHOW:
|
||||
mode = i;
|
||||
cbi_filename = optarg;
|
||||
required_mask = REQUIRED_MASK_SHOW;
|
||||
set_mask |= REQUIRED_MASK_FILENAME;
|
||||
break;
|
||||
case OPT_BOARD_VERSION:
|
||||
val = strtoul(optarg, &e, 0);
|
||||
if (val > USHRT_MAX || !*optarg || (e && *e)) {
|
||||
fprintf(stderr, "Invalid --board_version\n");
|
||||
parse_error = 1;
|
||||
}
|
||||
bi.version = val;
|
||||
set_mask |= REQUIRED_MASK_BOARD_VERSION;
|
||||
break;
|
||||
case OPT_OEM_ID:
|
||||
val = strtoul(optarg, &e, 0);
|
||||
if (val > UCHAR_MAX || !*optarg || (e && *e)) {
|
||||
fprintf(stderr, "Invalid --oem_id\n");
|
||||
parse_error = 1;
|
||||
}
|
||||
bi.oem_id = val;
|
||||
set_mask |= REQUIRED_MASK_OEM_ID;
|
||||
break;
|
||||
case OPT_SKU_ID:
|
||||
val = strtoul(optarg, &e, 0);
|
||||
if (val > UCHAR_MAX || !*optarg || (e && *e)) {
|
||||
fprintf(stderr, "Invalid --sku_id\n");
|
||||
parse_error = 1;
|
||||
}
|
||||
bi.sku_id = val;
|
||||
set_mask |= REQUIRED_MASK_SKU_ID;
|
||||
break;
|
||||
case OPT_SIZE:
|
||||
val = strtoul(optarg, &e, 0);
|
||||
if (val > USHRT_MAX || !*optarg || (e && *e)) {
|
||||
fprintf(stderr, "Invalid --size\n");
|
||||
parse_error = 1;
|
||||
}
|
||||
size = val;
|
||||
set_mask |= REQUIRED_MASK_SIZE;
|
||||
break;
|
||||
case OPT_ERASE_BYTE:
|
||||
erase = strtoul(optarg, &e, 0);
|
||||
if (!*optarg || (e && *e)) {
|
||||
fprintf(stderr, "Invalid --erase_byte\n");
|
||||
parse_error = 1;
|
||||
}
|
||||
break;
|
||||
case OPT_SHOW_ALL:
|
||||
show_all = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (parse_error) {
|
||||
print_help(argc, argv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (set_mask != required_mask) {
|
||||
fprintf(stderr, "Missing required arguments\n");
|
||||
print_help(argc, argv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case OPT_MODE_CREATE:
|
||||
return do_create(cbi_filename, size, erase, &bi);
|
||||
case OPT_MODE_SHOW:
|
||||
return do_show(cbi_filename, show_all);
|
||||
case OPT_MODE_NONE:
|
||||
default:
|
||||
fprintf(stderr, "Must specify a mode.\n");
|
||||
print_help(argc, argv);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user