1 /* radare - LGPL - Copyright 2013-2019 - pancake */
2 
3 #include <r_types.h>
4 #include <r_util.h>
5 #include <r_lib.h>
6 #include <r_bin.h>
7 #include "../i/private.h"
8 
check_buffer(RBuffer * buf)9 static bool check_buffer(RBuffer *buf) {
10 	r_return_val_if_fail (buf, false);
11 
12 	ut64 sz = r_buf_size (buf);
13 	if (sz <= 0xffff) {
14 		return false;
15 	}
16 
17 	ut8 b0 = r_buf_read8_at (buf, 0);
18 	if (b0 == 0xcf || b0 == 0x7f) {
19 		return false;
20 	}
21 
22 	const ut32 ep = sz - 0x10000 + 0xfff0; /* F000:FFF0 address */
23 	/* hacky check to avoid detecting multidex or MZ bins as bios */
24 	/* need better fix for this */
25 	ut8 tmp[3];
26 	int r = r_buf_read_at (buf, 0, tmp, sizeof (tmp));
27 	if (r <= 0 || !memcmp (tmp, "dex", 3) || !memcmp (tmp, "MZ", 2)) {
28 		return false;
29 	}
30 
31 	/* Check if this a 'jmp' opcode */
32 	ut8 bep = r_buf_read8_at (buf, ep);
33 	return bep == 0xea || bep == 0xe9;
34 }
35 
load_buffer(RBinFile * bf,void ** bin_obj,RBuffer * buf,ut64 loadaddr,Sdb * sdb)36 static bool load_buffer(RBinFile *bf, void **bin_obj, RBuffer *buf, ut64 loadaddr, Sdb *sdb) {
37 	if (!check_buffer (buf)) {
38 		return false;
39 	}
40 	*bin_obj = r_buf_ref (buf);
41 	return true;
42 }
43 
destroy(RBinFile * bf)44 static void destroy(RBinFile *bf) {
45 	r_buf_free (bf->o->bin_obj);
46 }
47 
baddr(RBinFile * bf)48 static ut64 baddr(RBinFile *bf) {
49 	return 0;
50 }
51 
52 /* accelerate binary load */
strings(RBinFile * bf)53 static RList *strings(RBinFile *bf) {
54 	return NULL;
55 }
56 
info(RBinFile * bf)57 static RBinInfo *info(RBinFile *bf) {
58 	RBinInfo *ret = NULL;
59 	if (!(ret = R_NEW0 (RBinInfo))) {
60 		return NULL;
61 	}
62 	ret->lang = NULL;
63 	ret->file = bf->file? strdup (bf->file): NULL;
64 	ret->type = strdup ("bios");
65 	ret->bclass = strdup ("1.0");
66 	ret->rclass = strdup ("bios");
67 	ret->os = strdup ("any");
68 	ret->subsystem = strdup ("unknown");
69 	ret->machine = strdup ("pc");
70 	ret->arch = strdup ("x86");
71 	ret->has_va = 1;
72 	ret->bits = 16;
73 	ret->big_endian = 0;
74 	ret->dbg_info = 0;
75 	return ret;
76 }
77 
sections(RBinFile * bf)78 static RList *sections(RBinFile *bf) {
79 	RList *ret = NULL;
80 	RBinSection *ptr = NULL;
81 	RBuffer *obj = bf->o->bin_obj;
82 
83 	if (!(ret = r_list_newf ((RListFree) r_bin_section_free))) {
84 		return NULL;
85 	}
86 	// program headers is another section
87 	if (!(ptr = R_NEW0 (RBinSection))) {
88 		return ret;
89 	}
90 	ptr->name = strdup ("bootblk"); // Maps to 0xF000:0000 segment
91 	ptr->vsize = ptr->size = 0x10000;
92 	ptr->paddr = r_buf_size (bf->buf) - ptr->size;
93 	ptr->vaddr = 0xf0000;
94 	ptr->perm = R_PERM_RWX;
95 	ptr->add = true;
96 	r_list_append (ret, ptr);
97 	// If image bigger than 128K - add one more section
98 	if (bf->size >= 0x20000) {
99 		if (!(ptr = R_NEW0 (RBinSection))) {
100 			return ret;
101 		}
102 		ptr->name = strdup ("_e000"); // Maps to 0xE000:0000 segment
103 		ptr->vsize = ptr->size = 0x10000;
104 		ptr->paddr = r_buf_size (obj) - 2 * ptr->size;
105 		ptr->vaddr = 0xe0000;
106 		ptr->perm = R_PERM_RWX;
107 		ptr->add = true;
108 		r_list_append (ret, ptr);
109 	}
110 	return ret;
111 }
112 
entries(RBinFile * bf)113 static RList *entries(RBinFile *bf) {
114 	RList *ret;
115 	RBinAddr *ptr = NULL;
116 	if (!(ret = r_list_new ())) {
117 		return NULL;
118 	}
119 	ret->free = free;
120 	if (!(ptr = R_NEW0 (RBinAddr))) {
121 		return ret;
122 	}
123 	ptr->paddr = 0; // 0x70000;
124 	ptr->vaddr = 0xffff0;
125 	r_list_append (ret, ptr);
126 	return ret;
127 }
128 
129 RBinPlugin r_bin_plugin_bios = {
130 	.name = "bios",
131 	.desc = "BIOS bin plugin",
132 	.license = "LGPL",
133 	.load_buffer = &load_buffer,
134 	.destroy = &destroy,
135 	.check_buffer = &check_buffer,
136 	.baddr = &baddr,
137 	.entries = entries,
138 	.sections = sections,
139 	.strings = &strings,
140 	.info = &info,
141 };
142 
143 #ifndef R2_PLUGIN_INCORE
144 R_API RLibStruct radare_plugin = {
145 	.type = R_LIB_TYPE_BIN,
146 	.data = &r_bin_plugin_bios,
147 	.version = R2_VERSION
148 };
149 #endif
150