aboutsummaryrefslogtreecommitdiff
path: root/utils/uvol/files/blockdev_common.uc
blob: ac601e78c4a70042fe7588a2696789f390e0bd1e (plain)
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
// SPDX-License-Identifier: GPL-2.0-or-later
// Helper functions used to identify the boot device

// adapted from /lib/functions.sh
let cmdline_get_var = function(var) {
	let cmdline = fs.open("/proc/cmdline", "r");
	let allargs = cmdline.read("all");
	cmdline.close();
	let ret = null;
	for (let arg in split(allargs, /[ \t\n]/)) {
		let el = split(arg, "=");
		if (shift(el) == var)
			return join("=", el);
	}
	return ret;
};

// adapted from /lib/upgrade/common.sh
let get_blockdevs = function() {
	let devs = [];
	for (let dev in fs.glob('/dev/*'))
		if (fs.stat(dev).type == "block")
			push(devs, split(dev, '/')[-1]);

	return devs;
};

// adapted from /lib/upgrade/common.sh
let get_uevent_major_minor = function(file) {
	let uevf = fs.open(file, "r");
	if (!uevf)
		return null;

	let r = {};
	let evl;
	while ((evl = uevf.read("line"))) {
	let ev = split(evl, '=');
		if (ev[0] == "MAJOR")
			r.major = +ev[1];
		if (ev[0] == "MINOR")
			r.minor = +ev[1];
	}
	uevf.close();
	return r;
};

// adapted from /lib/upgrade/common.sh
let get_bootdev = function(void) {
	let rootpart = cmdline_get_var("root");
	let uevent = null;

	if (wildcard(rootpart, "PARTUUID=[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]-[a-f0-9][a-f0-9]")) {
		let uuidarg = split(substr(rootpart, 9), '-')[0];
		for (let bd in get_blockdevs()) {
			let bdf = fs.open(sprintf("/dev/%s", bd), "r");
			bdf.seek(440);
			let bduuid = bdf.read(4);
			bdf.close();
			if (uuidarg == sprintf("%x%x%x%x", ord(bduuid, 3), ord(bduuid, 2), ord(bduuid, 1), ord(bduuid, 0))) {
				uevent = sprintf("/sys/class/block/%s/uevent", bd);
				break;
				}
			}
		} else if (wildcard(rootpart, "PARTUUID=????????-????-????-????-??????????0?/PARTNROFF=*") ||
			   wildcard(rootpart, "PARTUUID=????????-????-????-????-??????????02")) {
			let uuidarg = substr(split(substr(rootpart, 9), '/')[0], 0, -2) + "00";
			for (let bd in get_blockdevs()) {
				let bdf = fs.open(sprintf("/dev/%s", bd), "r");
				bdf.seek(568);
				let bduuid = bdf.read(16);
				bdf.close();
				if (!bduuid)
					continue;

			let uuid = sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
				ord(bduuid, 3), ord(bduuid, 2), ord(bduuid, 1), ord(bduuid, 0),
				ord(bduuid, 5), ord(bduuid, 4),
				ord(bduuid, 7), ord(bduuid, 6),
				ord(bduuid, 8), ord(bduuid, 9),
				ord(bduuid, 10), ord(bduuid, 11), ord(bduuid, 12), ord(bduuid, 13), ord(bduuid, 14), ord(bduuid, 15));

			if (uuidarg == uuid) {
				uevent = sprintf("/sys/class/block/%s/uevent", bd);
				break;
			}
		}
	} else if (wildcard(rootpart, "0x[a-f0-9][a-f0-9][a-f0-9]") ||
		   wildcard(rootpart, "0x[a-f0-9][a-f0-9][a-f0-9][a-f0-9]") ||
		   wildcard(rootpart, "[a-f0-9][a-f0-9][a-f0-9]") ||
		   wildcard(rootpart, "[a-f0-9][a-f0-9][a-f0-9][a-f0-9]")) {
		let devid = rootpart;
		if (substr(devid, 0, 2) == "0x")
			devid = substr(devid, 2);

		devid = hex(devid);
		for (let bd in get_blockdevs()) {
			let r = get_uevent_major_minor(sprintf("/sys/class/block/%s/uevent", bd));
			if (r && (r.major == devid / 256) && (r.minor == devid % 256)) {
				uevent = sprintf("/sys/class/block/%s/../uevent", bd);
				break;
			}
		}
	} else if (wildcard(rootpart, "/dev/*")) {
		uevent = sprintf("/sys/class/block/%s/../uevent", split(rootpart, '/')[-1]);
	}
	return get_uevent_major_minor(uevent);
};

// adapted from /lib/upgrade/common.sh
let get_partition = function(dev, num) {
	if (!dev)
		return null;

	for (let bd in get_blockdevs()) {
		let r = get_uevent_major_minor(sprintf("/sys/class/block/%s/uevent", bd));
		if (r.major == dev.major && r.minor == dev.minor + num) {
			return bd;
			break;
		}
	}
	return null;
};

blockdev_common = {};
blockdev_common.get_partition = get_partition;
blockdev_common.get_bootdev = get_bootdev;