Skip to content

Commit a27bdc3

Browse files
authored
Remove global state in the RBin.mbn plugin ##bin
1 parent 944ef52 commit a27bdc3

File tree

2 files changed

+131
-103
lines changed

2 files changed

+131
-103
lines changed

libr/bin/p/bin_mbn.c

Lines changed: 130 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,148 +1,167 @@
1-
/* radare2 - LGPL - Copyright 2015-2024 - pancake */
1+
/* radare2 - LGPL - Copyright 2015-2025 - pancake */
22

3-
#include <r_types.h>
4-
#include <r_util.h>
5-
#include <r_lib.h>
63
#include <r_bin.h>
74

85
typedef struct sbl_header {
96
ut32 load_index;
10-
ut32 version; // (flash_partition_version) 3 = nand
11-
ut32 paddr; // This + 40 is the start of the code in the file
12-
ut32 vaddr; // Where it's loaded in memory
13-
ut32 psize; // code_size + signature_size + cert_chain_size
14-
ut32 code_pa; // Only what's loaded to memory
7+
ut32 version; // (flash_partition_version) 3 = nand
8+
ut32 paddr; // This + 40 is the start of the code in the file
9+
ut32 vaddr; // Where it's loaded in memory
10+
ut32 psize; // code_size + signature_size + cert_chain_size
11+
ut32 code_pa; // Only what's loaded to memory
1512
ut32 sign_va;
1613
ut32 sign_sz;
17-
ut32 cert_va; // Max of 3 certs?
14+
ut32 cert_va; // Max of 3 certs?
1815
ut32 cert_sz;
1916
} SblHeader;
2017

21-
// TODO move this global into the bf->bobj
22-
static R_TH_LOCAL SblHeader sb = {0};
18+
/* Per-file SblHeader stored in bf->bo->bin_obj. Helper to fetch it. */
19+
static SblHeader *sbl_from_bf(RBinFile *bf) {
20+
return (bf && bf->bo && bf->bo->bin_obj) ? (SblHeader *)bf->bo->bin_obj : NULL;
21+
}
22+
23+
static void sbl_destroy(RBinFile *bf) {
24+
if (!bf || !bf->bo) {
25+
return;
26+
}
27+
if (bf->bo->bin_obj) {
28+
R_FREE (bf->bo->bin_obj);
29+
bf->bo->bin_obj = NULL;
30+
}
31+
}
32+
33+
static bool parse_sbl(RBuffer *b, SblHeader *h) {
34+
if (!b || !h) {
35+
return false;
36+
}
37+
int ret = r_buf_fread_at (b, 0, (ut8 *)h, "10i", 1);
38+
if (!ret) {
39+
return false;
40+
}
41+
return true;
42+
}
2343

2444
static bool check(RBinFile *bf, RBuffer *b) {
2545
R_RETURN_VAL_IF_FAIL (b, false);
2646
ut64 bufsz = r_buf_size (b);
47+
SblHeader h = { 0 };
48+
if (!parse_sbl (b, &h)) {
49+
return false;
50+
}
2751
if (sizeof (SblHeader) < bufsz) {
28-
int ret = r_buf_fread_at (b, 0, (ut8*)&sb, "10i", 1);
29-
if (!ret) {
30-
return false;
31-
}
32-
#if 0
33-
eprintf ("V=%d\n", sb.version);
34-
eprintf ("PA=0x%08x sz=0x%x\n", sb.paddr, sb.psize);
35-
eprintf ("VA=0x%08x sz=0x%x\n", sb.vaddr, sb.psize);
36-
eprintf ("CODE=0x%08x\n", sb.code_pa + sb.vaddr + 40);
37-
eprintf ("SIGN=0x%08x sz=0x%x\n", sb.sign_va, sb.sign_sz);
38-
if (sb.cert_sz > 0) {
39-
eprintf ("CERT=0x%08x sz=0x%x\n", sb.cert_va, sb.cert_sz);
40-
} else {
41-
eprintf ("No certificate found.\n");
42-
}
43-
#endif
44-
if (sb.version != 3) { // NAND
52+
if (h.version != 3) { // NAND
4553
return false;
4654
}
47-
if (sb.paddr + sizeof (SblHeader) > bufsz) { // NAND
55+
if (h.paddr + sizeof (SblHeader) > bufsz) { // NAND
4856
return false;
4957
}
50-
if (sb.vaddr < 0x100 || sb.psize > bufsz) { // NAND
58+
if (h.vaddr < 0x100 || h.psize > bufsz) { // NAND
5159
return false;
5260
}
53-
if (sb.cert_va < sb.vaddr) {
61+
if (h.cert_va < h.vaddr) {
5462
return false;
5563
}
56-
if (sb.cert_sz >= 0xf0000) {
64+
if (h.cert_sz >= 0xf0000) {
5765
return false;
5866
}
59-
if (sb.sign_va < sb.vaddr) {
67+
if (h.sign_va < h.vaddr) {
6068
return false;
6169
}
62-
if (sb.sign_sz >= 0xf0000) {
70+
if (h.sign_sz >= 0xf0000) {
6371
return false;
6472
}
65-
if (sb.load_index < 1 || sb.load_index > 0x40) {
73+
if (h.load_index < 1 || h.load_index > 0x40) {
6674
return false; // should be 0x19 ?
6775
}
68-
// TODO: Add more checks here
76+
// TODO: Add more checks here
6977
return true;
7078
}
7179
return false;
7280
}
7381

7482
static bool load(RBinFile *bf, RBuffer *b, ut64 loadaddr) {
75-
return check (bf, b);
83+
if (!bf || !bf->bo) {
84+
return false;
85+
}
86+
SblHeader *hdr = R_NEW0 (SblHeader);
87+
if (!parse_sbl (b, hdr)) {
88+
R_FREE (hdr);
89+
return false;
90+
}
91+
bf->bo->bin_obj = hdr;
92+
return true;
7693
}
7794

7895
static ut64 baddr(RBinFile *bf) {
79-
return sb.vaddr; // XXX
96+
SblHeader *sbl = sbl_from_bf (bf);
97+
return sbl ? sbl->vaddr : 0; // XXX
8098
}
8199

82-
static RList* entries(RBinFile *bf) {
83-
RList* ret = r_list_newf (free);
84-
if (ret) {
85-
RBinAddr *ptr = R_NEW0 (RBinAddr);
86-
if (ptr) {
87-
ptr->paddr = 40 + sb.code_pa;
88-
ptr->vaddr = 40 + sb.code_pa + sb.vaddr;
89-
r_list_append (ret, ptr);
100+
static RList *entries(RBinFile *bf) {
101+
RList *ret = r_list_newf (free);
102+
RBinAddr *ptr = R_NEW0 (RBinAddr);
103+
SblHeader *sbl = sbl_from_bf (bf);
104+
if (!sbl) {
105+
// try to read header directly from buffer as a fallback
106+
SblHeader h = { 0 };
107+
if (!parse_sbl (bf->buf, &h)) {
108+
r_list_free(ret);
109+
return NULL;
90110
}
111+
ptr->paddr = 40 + h.code_pa;
112+
ptr->vaddr = 40 + h.code_pa + h.vaddr;
113+
} else {
114+
ptr->paddr = 40 + sbl->code_pa;
115+
ptr->vaddr = 40 + sbl->code_pa + sbl->vaddr;
91116
}
117+
r_list_append (ret, ptr);
92118
return ret;
93119
}
94120

95-
static RList* sections(RBinFile *bf) {
96-
RBinSection *ptr = NULL;
97-
RList *ret = NULL;
98-
int rc;
99-
100-
if (!(ret = r_list_new ())) {
101-
return NULL;
102-
}
103-
ret->free = free;
104-
rc = r_buf_fread_at (bf->buf, 0, (ut8*)&sb, "10i", 1);
105-
if (!rc) {
106-
r_list_free (ret);
107-
return false;
121+
static RList *sections(RBinFile *bf) {
122+
RList *ret = r_list_newf (free);
123+
SblHeader *sbl = sbl_from_bf (bf);
124+
SblHeader h_local;
125+
SblHeader *h = sbl;
126+
if (!h) {
127+
int rc = r_buf_fread_at (bf->buf, 0, (ut8 *)&h_local, "10i", 1);
128+
if (!rc) {
129+
r_list_free (ret);
130+
return false;
131+
}
132+
h = &h_local;
108133
}
109134

110135
// add text segment
111-
if (!(ptr = R_NEW0 (RBinSection))) {
112-
return ret;
113-
}
114-
ptr->name = strdup ("text");
115-
ptr->size = sb.psize;
116-
ptr->vsize = sb.psize;
117-
ptr->paddr = sb.paddr + 40;
118-
ptr->vaddr = sb.vaddr;
136+
RBinSection *ptr = R_NEW0 (RBinSection);
137+
ptr->name = strdup("text");
138+
ptr->size = h->psize;
139+
ptr->vsize = h->psize;
140+
ptr->paddr = h->paddr + 40;
141+
ptr->vaddr = h->vaddr;
119142
ptr->perm = R_PERM_RX; // r-x
120143
ptr->add = true;
121144
ptr->has_strings = true;
122145
r_list_append (ret, ptr);
123146

124-
if (!(ptr = R_NEW0 (RBinSection))) {
125-
return ret;
126-
}
127-
ptr->name = strdup ("sign");
128-
ptr->size = sb.sign_sz;
129-
ptr->vsize = sb.sign_sz;
130-
ptr->paddr = sb.sign_va - sb.vaddr;
131-
ptr->vaddr = sb.sign_va;
147+
ptr = R_NEW0 (RBinSection);
148+
ptr->name = strdup("sign");
149+
ptr->size = h->sign_sz;
150+
ptr->vsize = h->sign_sz;
151+
ptr->paddr = h->sign_va - h->vaddr;
152+
ptr->vaddr = h->sign_va;
132153
ptr->perm = R_PERM_R; // r--
133154
ptr->has_strings = true;
134155
ptr->add = true;
135156
r_list_append (ret, ptr);
136157

137-
if (sb.cert_sz && sb.cert_va > sb.vaddr) {
138-
if (!(ptr = R_NEW0 (RBinSection))) {
139-
return ret;
140-
}
158+
if (h->cert_sz && h->cert_va > h->vaddr) {
159+
ptr = R_NEW0 (RBinSection);
141160
ptr->name = strdup ("cert");
142-
ptr->size = sb.cert_sz;
143-
ptr->vsize = sb.cert_sz;
144-
ptr->paddr = sb.cert_va - sb.vaddr;
145-
ptr->vaddr = sb.cert_va;
161+
ptr->size = h->cert_sz;
162+
ptr->vsize = h->cert_sz;
163+
ptr->paddr = h->cert_va - h->vaddr;
164+
ptr->vaddr = h->cert_va;
146165
ptr->perm = R_PERM_R; // r--
147166
ptr->has_strings = true;
148167
ptr->add = true;
@@ -151,30 +170,37 @@ static RList* sections(RBinFile *bf) {
151170
return ret;
152171
}
153172

154-
static RBinInfo* info(RBinFile *bf) {
173+
static RBinInfo *info(RBinFile *bf) {
155174
RBinInfo *ret = R_NEW0 (RBinInfo);
156-
if (R_LIKELY (ret)) {
157-
ret->file = strdup (bf->file);
158-
ret->bclass = strdup ("bootloader");
159-
ret->rclass = strdup ("mbn");
160-
ret->os = strdup ("MBN");
161-
ret->arch = strdup ("arm");
162-
ret->machine = strdup (ret->arch);
163-
ret->subsystem = strdup ("mbn");
164-
ret->type = strdup ("sbl"); // secondary boot loader
165-
ret->bits = 16;
166-
ret->has_va = true;
167-
ret->has_crypto = true; // must be false if there' no sign or cert sections
168-
ret->has_pi = false;
169-
ret->has_nx = false;
170-
ret->big_endian = false;
171-
ret->dbg_info = false;
172-
}
175+
ret->file = strdup (bf->file);
176+
ret->bclass = strdup ("bootloader");
177+
ret->rclass = strdup ("mbn");
178+
ret->os = strdup ("MBN");
179+
ret->arch = strdup ("arm");
180+
ret->machine = strdup (ret->arch);
181+
ret->subsystem = strdup ("mbn");
182+
ret->type = strdup ("sbl"); // secondary boot loader
183+
ret->bits = 16;
184+
ret->has_va = true;
185+
ret->has_crypto = true; // must be false if there' no sign or cert sections
186+
ret->has_pi = false;
187+
ret->has_nx = false;
188+
ret->big_endian = false;
189+
ret->dbg_info = false;
173190
return ret;
174191
}
175192

176193
static ut64 size(RBinFile *bf) {
177-
return sizeof (SblHeader) + sb.psize;
194+
SblHeader *sbl = sbl_from_bf (bf);
195+
if (sbl) {
196+
return sizeof (SblHeader) + sbl->psize;
197+
}
198+
// fallback: try reading header directly
199+
SblHeader h = { 0 };
200+
if (parse_sbl (bf->buf, &h)) {
201+
return sizeof (SblHeader) + h.psize;
202+
}
203+
return 0;
178204
}
179205

180206
RBinPlugin r_bin_plugin_mbn = {
@@ -192,6 +218,7 @@ RBinPlugin r_bin_plugin_mbn = {
192218
.entries = &entries,
193219
.sections = &sections,
194220
.info = &info,
221+
.destroy = &sbl_destroy,
195222
};
196223

197224
#ifndef R2_PLUGIN_INCORE

libr/bin/p/bin_mclf.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* radare2 - LGPL - Copyright 2025 - pancake */
22

33
// MCLF (MobiCore Load Format) loader based on public resources:
4+
// * https://gist.github.com/Stolas/e3ecaebaa7369b2d8d6c539b9ac2908e
45
// * https://github.com/quarkslab/sboot-binwalk/blob/master/plugins/mclf.py
56
// * https://github.com/NeatMonster/mclf-ghidra-loader
67
// * https://github.com/ghassani/mclf-ghidra-loader

0 commit comments

Comments
 (0)