Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
CTCaer
GitHub Repository: CTCaer/hekate
Path: blob/master/bootloader/hos/hos_config.c
3694 views
1
/*
2
* Copyright (c) 2018 naehrwert
3
* Copyright (c) 2018-2026 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 1;
35
36
return 0;
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 1;
44
45
return 0;
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 1;
53
54
return 0;
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*", 0);
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 1;
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 1;
112
}
113
DPRINTF("Loaded kip1 from SD (size %08X)\n", size);
114
list_append(&ctxt->kip1_list, &mkip1->link);
115
}
116
117
return 0;
118
}
119
120
int hos_config_kip1patch(launch_ctxt_t *ctxt, const char *value)
121
{
122
int len = strlen(value);
123
if (!len)
124
return 1;
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
146
return 0;
147
}
148
149
static int _config_svcperm(launch_ctxt_t *ctxt, const char *value)
150
{
151
if (*value == '1')
152
{
153
DPRINTF("Disabled SVC verification\n");
154
ctxt->svcperm = true;
155
}
156
157
return 0;
158
}
159
160
static int _config_debugmode(launch_ctxt_t *ctxt, const char *value)
161
{
162
if (*value == '1')
163
{
164
DPRINTF("Enabled Debug mode\n");
165
ctxt->debugmode = true;
166
}
167
168
return 0;
169
}
170
171
static int _config_stock(launch_ctxt_t *ctxt, const char *value)
172
{
173
if (*value == '1')
174
{
175
DPRINTF("Enabled stock mode\n");
176
ctxt->stock = true;
177
}
178
179
return 0;
180
}
181
182
static int _config_emummc_forced(launch_ctxt_t *ctxt, const char *value)
183
{
184
if (*value == '1')
185
{
186
DPRINTF("Forced emuMMC\n");
187
ctxt->emummc_forced = true;
188
}
189
190
return 0;
191
}
192
193
static int _config_kernel_proc_id(launch_ctxt_t *ctxt, const char *value)
194
{
195
if (*value == '1')
196
{
197
DPRINTF("Enabled kernel process id send/recv patching\n");
198
ctxt->patch_krn_proc_id = true;
199
}
200
201
return 0;
202
}
203
204
static int _config_dis_exo_user_exceptions(launch_ctxt_t *ctxt, const char *value)
205
{
206
if (*value == '1')
207
{
208
DPRINTF("Disabled exosphere user exception handlers\n");
209
ctxt->exo_ctx.no_user_exceptions = true;
210
}
211
212
return 0;
213
}
214
215
static int _config_exo_user_pmu_access(launch_ctxt_t *ctxt, const char *value)
216
{
217
if (*value == '1')
218
{
219
DPRINTF("Enabled user access to PMU\n");
220
ctxt->exo_ctx.user_pmu = true;
221
}
222
223
return 0;
224
}
225
226
static int _config_exo_force_mem_mode(launch_ctxt_t *ctxt, const char *value)
227
{
228
// Override key found.
229
ctxt->exo_ctx.force_mem_mode = zalloc(sizeof(bool));
230
231
if (*value == '1')
232
{
233
DPRINTF("Enabled Auto Memory Mode\n");
234
*ctxt->exo_ctx.force_mem_mode = true;
235
}
236
237
return 0;
238
}
239
240
static int _config_exo_usb3_force(launch_ctxt_t *ctxt, const char *value)
241
{
242
// Override key found.
243
ctxt->exo_ctx.usb3_force = zalloc(sizeof(bool));
244
245
if (*value == '1')
246
{
247
DPRINTF("Enabled USB 3.0\n");
248
*ctxt->exo_ctx.usb3_force = true;
249
}
250
251
return 0;
252
}
253
254
static int _config_exo_cal0_blanking(launch_ctxt_t *ctxt, const char *value)
255
{
256
// Override key found.
257
ctxt->exo_ctx.cal0_blank = zalloc(sizeof(bool));
258
259
if (*value == '1')
260
{
261
DPRINTF("Enabled prodinfo blanking\n");
262
*ctxt->exo_ctx.cal0_blank = true;
263
}
264
265
return 0;
266
}
267
268
static int _config_exo_cal0_writes_enable(launch_ctxt_t *ctxt, const char *value)
269
{
270
// Override key found.
271
ctxt->exo_ctx.cal0_allow_writes_sys = zalloc(sizeof(bool));
272
273
if (*value == '1')
274
{
275
DPRINTF("Enabled prodinfo writes\n");
276
*ctxt->exo_ctx.cal0_allow_writes_sys = true;
277
}
278
279
return 0;
280
}
281
282
static int _config_pkg3(launch_ctxt_t *ctxt, const char *value)
283
{
284
return parse_pkg3(ctxt, value);
285
}
286
287
static int _config_exo_fatal_payload(launch_ctxt_t *ctxt, const char *value)
288
{
289
ctxt->exofatal = sd_file_read(value, &ctxt->exofatal_size);
290
if (!ctxt->exofatal)
291
return 1;
292
293
return 0;
294
}
295
296
static int _config_ucid(launch_ctxt_t *ctxt, const char *value)
297
{
298
// Override uCID if set.
299
ctxt->ucid = atoi(value);
300
301
return 0;
302
}
303
304
typedef struct _cfg_handler_t
305
{
306
const char *key;
307
int (*handler)(launch_ctxt_t *ctxt, const char *value);
308
} cfg_handler_t;
309
310
static const cfg_handler_t _config_handlers[] = {
311
{ "stock", _config_stock },
312
{ "warmboot", _config_warmboot },
313
{ "secmon", _config_secmon },
314
{ "kernel", _config_kernel },
315
{ "kip1", _config_kip1 },
316
{ "kip1patch", hos_config_kip1patch },
317
{ "fullsvcperm", _config_svcperm },
318
{ "debugmode", _config_debugmode },
319
{ "kernelprocid", _config_kernel_proc_id },
320
321
// To override elements from PKG3, it should be set before others.
322
{ "pkg3", _config_pkg3 },
323
{ "fss0", _config_pkg3 },
324
325
{ "exofatal", _config_exo_fatal_payload},
326
{ "emummcforce", _config_emummc_forced },
327
{ "nouserexceptions", _config_dis_exo_user_exceptions },
328
{ "userpmu", _config_exo_user_pmu_access },
329
{ "memmode", _config_exo_force_mem_mode },
330
{ "usb3force", _config_exo_usb3_force },
331
{ "cal0blank", _config_exo_cal0_blanking },
332
{ "cal0writesys", _config_exo_cal0_writes_enable },
333
{ "ucid", _config_ucid },
334
{ NULL, NULL },
335
};
336
337
int hos_parse_boot_config(launch_ctxt_t *ctxt)
338
{
339
if (!ctxt->cfg)
340
return 0;
341
342
// Check each config key.
343
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link)
344
{
345
for (u32 i = 0; _config_handlers[i].key; i++)
346
{
347
// If key matches, call its handler.
348
if (!strcmp(_config_handlers[i].key, kv->key))
349
{
350
if (_config_handlers[i].handler(ctxt, kv->val))
351
{
352
gfx_con.mute = false;
353
EPRINTFARGS("Error while loading %s:\n%s", kv->key, kv->val);
354
355
return 1;
356
}
357
358
break;
359
}
360
}
361
}
362
363
return 0;
364
}
365
366