forked from msm8916-mainline/lk2nd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
fs_boot.c
190 lines (156 loc) · 4.31 KB
/
fs_boot.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// SPDX-License-Identifier: GPL-2.0-only
#include <debug.h>
#include <target.h>
#include <string.h>
#include <lib/bio.h>
#include <lib/fs.h>
#include "fs_boot.h"
struct fs_boot_data fs_boot_data;
static const char *bootable_parts[] = {
"system",
"cache",
"userdata",
};
static bool fsboot_bootable_part(char *label)
{
int i;
for (i = 0; i < ARRAY_SIZE(bootable_parts); ++i)
if (strcmp(label, bootable_parts[i]) == 0)
return true;
return false;
}
static enum rproc_mode fsboot_load_rproc_mode(const char *path)
{
char mode[9] = {0};
char *lf;
int ret;
ret = fs_load_file(path, mode, sizeof(mode) - 1);
if (ret < 0) {
dprintf(INFO, "Failed to load rproc mode: %d\n", ret);
return RPROC_MODE_UNKNOWN;
}
/* Trim new line from string */
lf = strchr(mode, '\n');
if (lf)
*lf = 0;
if (strcmp(mode, "all") == 0)
return RPROC_MODE_ALL;
if (strcmp(mode, "no-modem") == 0)
return RPROC_MODE_NO_MODEM;
if (strcmp(mode, "none") == 0)
return RPROC_MODE_NONE;
dprintf(CRITICAL, "Unknown rproc mode: %s\n", mode);
return RPROC_MODE_UNKNOWN;
}
/* Only iterate through files if target is NULL */
static int fsboot_fs_load_img(char *dev_name, void* target, size_t sz)
{
struct dirhandle *dirh;
struct dirent dirent;
char image_path[128] = "/mnt/";
int ret = -1;
bool path_valid = false;
if (fs_mount("/mnt", "ext2", dev_name) < 0)
return -1;
ret = fs_open_dir("/mnt", &dirh);
if (ret < 0) {
dprintf(SPEW, "fs_open_dir ret = %d\n", ret);
goto out;
}
while (fs_read_dir(dirh, &dirent) >= 0) {
if (!target)
dprintf(SPEW, "| /%s/%s\n", dev_name, dirent.name);
if (!path_valid && strncmp(dirent.name, "boot.img", 7) == 0) {
strcpy(&image_path[strlen("/mnt/")], dirent.name);
dprintf(INFO, "Found boot image: %s : %s\n", dev_name, image_path);
path_valid = true;
} else if (strncmp(dirent.name, "lk2nd_skip", 10) == 0) {
dprintf(INFO, "Partition skipped: %s\n", dev_name);
fs_close_dir(dirh);
goto out;
}
}
fs_close_dir(dirh);
if (target && path_valid)
ret = fs_load_file(image_path, target, sz);
if (ret >= 0 && path_valid && !fs_boot_data.dev) {
fs_boot_data.rproc_mode = fsboot_load_rproc_mode("/mnt/lk2nd_rproc_mode");
dprintf(INFO, "Boot partition rproc mode: %d\n", fs_boot_data.rproc_mode);
}
out:
fs_unmount("/mnt");
return ret;
}
static int fsboot_find_and_boot(int bdev_id, void* target, size_t sz)
{
int i = 0, j = 0, ret = 0;
char dev_name[128];
bdev_t *dev = NULL;
/* HACK: There is no hd1p0 for some reason */
if (bdev_id == 1)
i = 1;
sprintf(dev_name, "hd%d", bdev_id);
dev = bio_open(dev_name);
if (!dev) {
dprintf(CRITICAL, "fs-boot: Can't open %s\n", dev_name);
return -1;
}
bio_close(dev);
if (!target)
dprintf(SPEW, "fs-boot: Looking at %s:\n", dev_name);
sprintf(dev_name, "hd%dp%d", bdev_id, i);
while (dev = bio_open(dev_name)) {
/* Only probe useful partitions if looking at emmc */
if (bdev_id == FS_BOOT_DEV_EMMC && !fsboot_bootable_part(dev->label)) {
bio_close(dev);
i++;
sprintf(dev_name, "hd%dp%d", bdev_id, i);
continue;
}
if (!target)
dprintf(SPEW, "%.8s: %.10s (%6llu MiB): \n",dev->name, dev->label, dev->size / (1024 * 1024));
bio_close(dev);
ret = fsboot_fs_load_img(dev_name, target, sz);
if (ret >= 0)
fs_boot_data.dev = bdev_id;
if (target && ret >= 0)
return ret;
/* Only check subpartitions on emmc */
if (ret < 0 && bdev_id == FS_BOOT_DEV_EMMC) {
j = 0;
sprintf(dev_name, "hd%dp%dp%d", bdev_id, i, j);
while (dev = bio_open(dev_name)) {
if (!target)
dprintf(SPEW, "%.8s: %.10s (%6llu MiB): \n",dev->name, dev->label, dev->size / (1024 * 1024));
bio_close(dev);
ret = fsboot_fs_load_img(dev_name, target, sz);
if (ret >= 0)
fs_boot_data.dev = bdev_id;
if (target && ret >= 0)
return ret;
j++;
sprintf(dev_name, "hd%dp%dp%d", bdev_id, i, j);
}
}
i++;
sprintf(dev_name, "hd%dp%d", bdev_id, i);
}
return -1;
}
void fsboot_test(void)
{
dprintf(SPEW, "fs-boot: Scanned devices:\n");
fsboot_find_and_boot(FS_BOOT_DEV_SDCARD, NULL, 0);
fsboot_find_and_boot(FS_BOOT_DEV_EMMC, NULL, 0);
}
int fsboot_boot_first(void* target, size_t sz)
{
int ret = -1;
ret = fsboot_find_and_boot(FS_BOOT_DEV_SDCARD, target, sz);
if (ret > 0)
return ret;
ret = fsboot_find_and_boot(FS_BOOT_DEV_EMMC, target, sz);
if (ret > 0)
return ret;
return -1;
}