/* 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.
*
* Stub implementations of firmware-provided API functions.
*/
#include <execinfo.h>
#include <stdint.h>
#define _STUB_IMPLEMENTATION_
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include "vboot_api.h"
#define MAX_STACK_LEVELS 10
/* Keep track of nodes that are currently allocated */
struct alloc_node {
struct alloc_node *next;
void *ptr;
size_t size;
void *bt_buffer[MAX_STACK_LEVELS];
int bt_levels;
};
static struct alloc_node *alloc_head;
static void print_stacktrace(void)
{
void *buffer[MAX_STACK_LEVELS];
int levels = backtrace(buffer, MAX_STACK_LEVELS);
// print to stderr (fd = 2), and remove this function from the trace
backtrace_symbols_fd(buffer + 1, levels - 1, 2);
}
void *VbExMalloc(size_t size)
{
struct alloc_node *node;
void *p = malloc(size);
if (!p) {
/* Fatal Error. We must abort. */
abort();
}
node = malloc(sizeof(*node));
if (!node)
abort();
node->next = alloc_head;
node->ptr = p;
node->size = size;
node->bt_levels = backtrace(node->bt_buffer, MAX_STACK_LEVELS);
alloc_head = node;
return p;
}
static struct alloc_node **find_node(void *ptr)
{
struct alloc_node **nodep;
for (nodep = &alloc_head; *nodep; nodep = &(*nodep)->next)
if ((*nodep)->ptr == ptr)
return nodep;
return NULL;
}
void VbExFree(void *ptr)
{
struct alloc_node **nodep, *next;
nodep = find_node(ptr);
if (nodep) {
next = (*nodep)->next;
free(*nodep);
*nodep = next;
} else {
fprintf(stderr, "\n>>>>>> Invalid VbExFree() %p\n", ptr);
fflush(stderr);
print_stacktrace();
/*
* Fall through and do the free() so we get normal error
* handling.
*/
}
free(ptr);
}
VbError_t VbExHashFirmwareBody(VbCommonParams *cparams,
uint32_t firmware_index)
{
return VBERROR_SUCCESS;
}
int vboot_api_stub_check_memory(void)
{
struct alloc_node *node, *next;
if (!alloc_head)
return 0;
/*
* Make sure we free all our memory so that valgrind doesn't complain
* about leaked memory.
*/
fprintf(stderr, "\nWarning, some allocations not freed:");
for (node = alloc_head; node; node = next) {
next = node->next;
fprintf(stderr, "\nptr=%p, size=%zd\n", node->ptr, node->size);
fflush(stderr);
backtrace_symbols_fd(node->bt_buffer + 1, node->bt_levels - 1,
2);
free(node);
}
return -1;
}