1/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 2 * Use of this source code is governed by a BSD-style license that can be 3 * found in the LICENSE file. 4 * 5 * Stub implementations of firmware-provided API functions. 6 */ 7 8#include <execinfo.h> 9#include <stdint.h> 10 11#define _STUB_IMPLEMENTATION_ 12 13#include <stdarg.h> 14#include <stdio.h> 15#include <stdlib.h> 16#include <string.h> 17#include <sys/time.h> 18 19#include "vboot_api.h" 20 21#define MAX_STACK_LEVELS 10 22 23 24/* Keep track of nodes that are currently allocated */ 25struct alloc_node { 26 struct alloc_node *next; 27 void *ptr; 28 size_t size; 29 void *bt_buffer[MAX_STACK_LEVELS]; 30 int bt_levels; 31}; 32 33static struct alloc_node *alloc_head; 34 35static void print_stacktrace(void) 36{ 37 void *buffer[MAX_STACK_LEVELS]; 38 int levels = backtrace(buffer, MAX_STACK_LEVELS); 39 40 // print to stderr (fd = 2), and remove this function from the trace 41 backtrace_symbols_fd(buffer + 1, levels - 1, 2); 42} 43 44void *VbExMalloc(size_t size) 45{ 46 struct alloc_node *node; 47 void *p = malloc(size); 48 49 if (!p) { 50 /* Fatal Error. We must abort. */ 51 abort(); 52 } 53 54 node = malloc(sizeof(*node)); 55 if (!node) 56 abort(); 57 node->next = alloc_head; 58 node->ptr = p; 59 node->size = size; 60 node->bt_levels = backtrace(node->bt_buffer, MAX_STACK_LEVELS); 61 alloc_head = node; 62 63 return p; 64} 65 66static struct alloc_node **find_node(void *ptr) 67{ 68 struct alloc_node **nodep; 69 70 for (nodep = &alloc_head; *nodep; nodep = &(*nodep)->next) 71 if ((*nodep)->ptr == ptr) 72 return nodep; 73 74 return NULL; 75} 76 77void VbExFree(void *ptr) 78{ 79 struct alloc_node **nodep, *next; 80 81 nodep = find_node(ptr); 82 if (nodep) { 83 next = (*nodep)->next; 84 free(*nodep); 85 *nodep = next; 86 } else { 87 fprintf(stderr, "\n>>>>>> Invalid VbExFree() %p\n", ptr); 88 fflush(stderr); 89 print_stacktrace(); 90 /* 91 * Fall through and do the free() so we get normal error 92 * handling. 93 */ 94 } 95 96 free(ptr); 97} 98 99VbError_t VbExHashFirmwareBody(VbCommonParams *cparams, 100 uint32_t firmware_index) 101{ 102 return VBERROR_SUCCESS; 103} 104 105int vboot_api_stub_check_memory(void) 106{ 107 struct alloc_node *node, *next; 108 109 if (!alloc_head) 110 return 0; 111 112 /* 113 * Make sure we free all our memory so that valgrind doesn't complain 114 * about leaked memory. 115 */ 116 fprintf(stderr, "\nWarning, some allocations not freed:"); 117 for (node = alloc_head; node; node = next) { 118 next = node->next; 119 fprintf(stderr, "\nptr=%p, size=%zd\n", node->ptr, node->size); 120 fflush(stderr); 121 backtrace_symbols_fd(node->bt_buffer + 1, node->bt_levels - 1, 122 2); 123 free(node); 124 } 125 126 return -1; 127} 128