Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
CTCaer
GitHub Repository: CTCaer/hekate
Path: blob/master/bootloader/hos/hos_config.c
1476 views
1
/*
2
* Copyright (c) 2018 naehrwert
3
* Copyright (c) 2018-2025 CTCaer
4
*
5
* This program is free software; you can redistribute it and/or modify it
6
* under the terms and conditions of the GNU General Public License,
7
* version 2, as published by the Free Software Foundation.
8
*
9
* This program is distributed in the hope it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
* more details.
13
*
14
* You should have received a copy of the GNU General Public License
15
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
*/
17
18
#include <string.h>
19
20
#include <bdk.h>
21
22
#include "hos.h"
23
#include "hos_config.h"
24
#include "pkg3.h"
25
#include <libs/fatfs/ff.h>
26
27
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
28
#define DPRINTF(...)
29
30
static int _config_warmboot(launch_ctxt_t *ctxt, const char *value)
31
{
32
ctxt->warmboot = sd_file_read(value, &ctxt->warmboot_size);
33
if (!ctxt->warmboot)
34
return 0;
35
36
return 1;
37
}
38
39
static int _config_secmon(launch_ctxt_t *ctxt, const char *value)
40
{
41
ctxt->secmon = sd_file_read(value, &ctxt->secmon_size);
42
if (!ctxt->secmon)
43
return 0;
44
45
return 1;
46
}
47
48
static int _config_kernel(launch_ctxt_t *ctxt, const char *value)
49
{
50
ctxt->kernel = sd_file_read(value, &ctxt->kernel_size);
51
if (!ctxt->kernel)
52
return 0;
53
54
return 1;
55
}
56
57
static int _config_kip1(launch_ctxt_t *ctxt, const char *value)
58
{
59
u32 size;
60
61
if (value[strlen(value) - 1] == '*')
62
{
63
char *dir = (char *)malloc(256);
64
strcpy(dir, value);
65
66
u32 dirlen = 0;
67
dir[strlen(dir) - 2] = 0;
68
dirlist_t *filelist = dirlist(dir, "*.kip*", false, false);
69
70
strcat(dir, "/");
71
dirlen = strlen(dir);
72
73
u32 i = 0;
74
if (filelist)
75
{
76
while (true)
77
{
78
if (!filelist->name[i])
79
break;
80
81
strcpy(dir + dirlen, filelist->name[i]);
82
83
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
84
mkip1->kip1 = sd_file_read(dir, &size);
85
if (!mkip1->kip1)
86
{
87
free(mkip1);
88
free(dir);
89
free(filelist);
90
91
return 0;
92
}
93
DPRINTF("Loaded kip1 from SD (size %08X)\n", size);
94
list_append(&ctxt->kip1_list, &mkip1->link);
95
96
i++;
97
}
98
}
99
100
free(dir);
101
free(filelist);
102
}
103
else
104
{
105
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
106
mkip1->kip1 = sd_file_read(value, &size);
107
if (!mkip1->kip1)
108
{
109
free(mkip1);
110
111
return 0;
112
}
113
DPRINTF("Loaded kip1 from SD (size %08X)\n", size);
114
list_append(&ctxt->kip1_list, &mkip1->link);
115
}
116
117
return 1;
118
}
119
120
int config_kip1patch(launch_ctxt_t *ctxt, const char *value)
121
{
122
int len = strlen(value);
123
if (!len)
124
return 0;
125
126
if (ctxt->kip1_patches == NULL)
127
{
128
ctxt->kip1_patches = malloc(len + 1);
129
memcpy(ctxt->kip1_patches, value, len);
130
ctxt->kip1_patches[len] = 0;
131
}
132
else
133
{
134
char *old_addr = ctxt->kip1_patches;
135
int old_len = strlen(old_addr);
136
137
ctxt->kip1_patches = malloc(old_len + 1 + len + 1);
138
memcpy(ctxt->kip1_patches, old_addr, old_len);
139
free(old_addr);
140
141
ctxt->kip1_patches[old_len++] = ',';
142
memcpy(&ctxt->kip1_patches[old_len], value, len);
143
ctxt->kip1_patches[old_len + len] = 0;
144
}
145
return 1;
146
}
147
148
static int _config_svcperm(launch_ctxt_t *ctxt, const char *value)
149
{
150
if (*value == '1')
151
{
152
DPRINTF("Disabled SVC verification\n");
153
ctxt->svcperm = true;
154
}
155
return 1;
156
}
157
158
static int _config_debugmode(launch_ctxt_t *ctxt, const char *value)
159
{
160
if (*value == '1')
161
{
162
DPRINTF("Enabled Debug mode\n");
163
ctxt->debugmode = true;
164
}
165
return 1;
166
}
167
168
static int _config_stock(launch_ctxt_t *ctxt, const char *value)
169
{
170
if (*value == '1')
171
{
172
DPRINTF("Disabled all patching\n");
173
ctxt->stock = true;
174
}
175
return 1;
176
}
177
178
static int _config_emummc_forced(launch_ctxt_t *ctxt, const char *value)
179
{
180
if (*value == '1')
181
{
182
DPRINTF("Forced emuMMC\n");
183
ctxt->emummc_forced = true;
184
}
185
return 1;
186
}
187
188
static int _config_kernel_proc_id(launch_ctxt_t *ctxt, const char *value)
189
{
190
if (*value == '1')
191
{
192
DPRINTF("Enabled kernel process id send/recv patching\n");
193
ctxt->patch_krn_proc_id = true;
194
}
195
return 1;
196
}
197
198
static int _config_dis_exo_user_exceptions(launch_ctxt_t *ctxt, const char *value)
199
{
200
if (*value == '1')
201
{
202
DPRINTF("Disabled exosphere user exception handlers\n");
203
ctxt->exo_ctx.no_user_exceptions = true;
204
}
205
return 1;
206
}
207
208
static int _config_exo_user_pmu_access(launch_ctxt_t *ctxt, const char *value)
209
{
210
if (*value == '1')
211
{
212
DPRINTF("Enabled user access to PMU\n");
213
ctxt->exo_ctx.user_pmu = true;
214
}
215
return 1;
216
}
217
218
static int _config_exo_usb3_force(launch_ctxt_t *ctxt, const char *value)
219
{
220
// Override key found.
221
ctxt->exo_ctx.usb3_force = zalloc(sizeof(bool));
222
223
if (*value == '1')
224
{
225
DPRINTF("Enabled USB 3.0\n");
226
*ctxt->exo_ctx.usb3_force = true;
227
}
228
return 1;
229
}
230
231
static int _config_exo_cal0_blanking(launch_ctxt_t *ctxt, const char *value)
232
{
233
// Override key found.
234
ctxt->exo_ctx.cal0_blank = zalloc(sizeof(bool));
235
236
if (*value == '1')
237
{
238
DPRINTF("Enabled prodinfo blanking\n");
239
*ctxt->exo_ctx.cal0_blank = true;
240
}
241
return 1;
242
}
243
244
static int _config_exo_cal0_writes_enable(launch_ctxt_t *ctxt, const char *value)
245
{
246
// Override key found.
247
ctxt->exo_ctx.cal0_allow_writes_sys = zalloc(sizeof(bool));
248
249
if (*value == '1')
250
{
251
DPRINTF("Enabled prodinfo writes\n");
252
*ctxt->exo_ctx.cal0_allow_writes_sys = true;
253
}
254
255
return 1;
256
}
257
258
static int _config_pkg3(launch_ctxt_t *ctxt, const char *value)
259
{
260
return parse_pkg3(ctxt, value);
261
}
262
263
static int _config_exo_fatal_payload(launch_ctxt_t *ctxt, const char *value)
264
{
265
ctxt->exofatal = sd_file_read(value, &ctxt->exofatal_size);
266
if (!ctxt->exofatal)
267
return 0;
268
269
return 1;
270
}
271
272
static int _config_ucid(launch_ctxt_t *ctxt, const char *value)
273
{
274
// Override uCID if set.
275
ctxt->ucid = atoi(value);
276
277
return 1;
278
}
279
280
typedef struct _cfg_handler_t
281
{
282
const char *key;
283
int (*handler)(launch_ctxt_t *ctxt, const char *value);
284
} cfg_handler_t;
285
286
static const cfg_handler_t _config_handlers[] = {
287
{ "stock", _config_stock },
288
{ "warmboot", _config_warmboot },
289
{ "secmon", _config_secmon },
290
{ "kernel", _config_kernel },
291
{ "kip1", _config_kip1 },
292
{ "kip1patch", config_kip1patch },
293
{ "fullsvcperm", _config_svcperm },
294
{ "debugmode", _config_debugmode },
295
{ "kernelprocid", _config_kernel_proc_id },
296
297
// To override elements from PKG3, it should be set before others.
298
{ "pkg3", _config_pkg3 },
299
{ "fss0", _config_pkg3 },
300
301
{ "exofatal", _config_exo_fatal_payload},
302
{ "emummcforce", _config_emummc_forced },
303
{ "nouserexceptions", _config_dis_exo_user_exceptions },
304
{ "userpmu", _config_exo_user_pmu_access },
305
{ "usb3force", _config_exo_usb3_force },
306
{ "cal0blank", _config_exo_cal0_blanking },
307
{ "cal0writesys", _config_exo_cal0_writes_enable },
308
{ "ucid", _config_ucid },
309
{ NULL, NULL },
310
};
311
312
int parse_boot_config(launch_ctxt_t *ctxt)
313
{
314
if (!ctxt->cfg)
315
return 1;
316
317
// Check each config key.
318
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link)
319
{
320
for (u32 i = 0; _config_handlers[i].key; i++)
321
{
322
// If key matches, call its handler.
323
if (!strcmp(_config_handlers[i].key, kv->key))
324
{
325
if (!_config_handlers[i].handler(ctxt, kv->val))
326
{
327
gfx_con.mute = false;
328
EPRINTFARGS("Error while loading %s:\n%s", kv->key, kv->val);
329
330
return 0;
331
}
332
333
break;
334
}
335
}
336
}
337
338
return 1;
339
}
340
341