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