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 */
25 struct 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 
33 static struct alloc_node *alloc_head;
34 
print_stacktrace(void)35 static 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 
VbExMalloc(size_t size)44 void *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 
find_node(void * ptr)66 static 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 
VbExFree(void * ptr)77 void 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 
VbExHashFirmwareBody(VbCommonParams * cparams,uint32_t firmware_index)99 VbError_t VbExHashFirmwareBody(VbCommonParams *cparams,
100                                uint32_t firmware_index)
101 {
102 	return VBERROR_SUCCESS;
103 }
104 
vboot_api_stub_check_memory(void)105 int 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