]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - INSTALL/tool/ventoy_lib.sh
1.1.07 release
[Ventoy.git] / INSTALL / tool / ventoy_lib.sh
1 #!/bin/sh
2
3 #Ventoy partition 32MB
4 VENTOY_PART_SIZE=33554432
5 VENTOY_PART_SIZE_MB=32
6 VENTOY_SECTOR_SIZE=512
7 VENTOY_SECTOR_NUM=65536
8
9 ventoy_false() {
10 [ "1" = "2" ]
11 }
12
13 ventoy_true() {
14 [ "1" = "1" ]
15 }
16
17
18 vtinfo() {
19 echo -e "\033[32m$*\033[0m"
20 }
21
22 vtwarn() {
23 echo -e "\033[33m$*\033[0m"
24 }
25
26
27 vterr() {
28 echo -e "\033[31m$*\033[0m"
29 }
30
31 vtdebug() {
32 echo "$*" >> ./log.txt
33 }
34
35 vtoy_gen_uuid() {
36 if uuid -F BIN > /dev/null 2>&1; then
37 uuid -F BIN
38 elif uuidgen -V > /dev/null 2>&1; then
39 a=$(uuidgen | sed 's/-//g')
40 echo -en "\x${a:0:2}\x${a:2:2}\x${a:4:2}\x${a:6:2}\x${a:8:2}\x${a:10:2}\x${a:12:2}\x${a:14:2}\x${a:16:2}\x${a:18:2}\x${a:20:2}\x${a:22:2}\x${a:24:2}\x${a:26:2}\x${a:28:2}\x${a:30:2}"
41 elif python -V > /dev/null 2>&1; then
42 a=$(python -c 'import sys,uuid; sys.stdout.write(uuid.uuid4().hex)')
43 echo -en "\x${a:0:2}\x${a:2:2}\x${a:4:2}\x${a:6:2}\x${a:8:2}\x${a:10:2}\x${a:12:2}\x${a:14:2}\x${a:16:2}\x${a:18:2}\x${a:20:2}\x${a:22:2}\x${a:24:2}\x${a:26:2}\x${a:28:2}\x${a:30:2}"
44 elif [ -e /dev/urandom ]; then
45 dd if=/dev/urandom bs=1 count=16 status=none
46 else
47 datestr=$(date +%N%N%N%N%N)
48 a=${datestr:0:32}
49 echo -en "\x${a:0:2}\x${a:2:2}\x${a:4:2}\x${a:6:2}\x${a:8:2}\x${a:10:2}\x${a:12:2}\x${a:14:2}\x${a:16:2}\x${a:18:2}\x${a:20:2}\x${a:22:2}\x${a:24:2}\x${a:26:2}\x${a:28:2}\x${a:30:2}"
50 fi
51 }
52
53 check_tool_work_ok() {
54
55 if echo 1 | hexdump > /dev/null; then
56 vtdebug "hexdump test ok ..."
57 else
58 vtdebug "hexdump test fail ..."
59 ventoy_false
60 return
61 fi
62
63 if mkexfatfs -V > /dev/null; then
64 vtdebug "mkexfatfs test ok ..."
65 else
66 vtdebug "mkexfatfs test fail ..."
67 ventoy_false
68 return
69 fi
70
71 if vtoycli fat -T; then
72 vtdebug "vtoycli fat test ok ..."
73 else
74 vtdebug "vtoycli fat test fail ..."
75 ventoy_false
76 return
77 fi
78
79 vtdebug "tool check success ..."
80 ventoy_true
81 }
82
83
84 get_disk_part_name() {
85 DISK=$1
86
87 if echo $DISK | grep -q "/dev/loop"; then
88 echo ${DISK}p${2}
89 elif echo $DISK | grep -q "/dev/nvme[0-9][0-9]*n[0-9]"; then
90 echo ${DISK}p${2}
91 elif echo $DISK | grep -q "/dev/mmcblk[0-9]"; then
92 echo ${DISK}p${2}
93 elif echo $DISK | grep -q "/dev/nbd[0-9]"; then
94 echo ${DISK}p${2}
95 elif echo $DISK | grep -q "/dev/zd[0-9]"; then
96 echo ${DISK}p${2}
97 elif echo $DISK | grep -q "/dev/md[0-9]"; then
98 echo ${DISK}p${2}
99 else
100 echo ${DISK}${2}
101 fi
102 }
103
104 check_umount_disk() {
105 DiskOrPart="$1"
106 grep "^${DiskOrPart}" /proc/mounts | while read mtline; do
107 mtpnt=$(echo $mtline | awk '{print $2}')
108 vtdebug "Trying to umount $mtpnt ..."
109 umount $mtpnt >/dev/null 2>&1
110 done
111 }
112
113 get_ventoy_version_from_cfg() {
114 if grep -q 'set.*VENTOY_VERSION=' $1; then
115 grep 'set.*VENTOY_VERSION=' $1 | awk -F'"' '{print $2}'
116 else
117 echo 'none'
118 fi
119 }
120
121 is_disk_contains_ventoy() {
122 DISK=$1
123
124 PART1=$(get_disk_part_name $1 1)
125 PART2=$(get_disk_part_name $1 2)
126
127 if [ -e /sys/class/block/${PART2#/dev/}/size ]; then
128 SIZE=$(cat /sys/class/block/${PART2#/dev/}/size)
129 else
130 SIZE=0
131 fi
132
133 if ! [ -b $PART1 ]; then
134 vtdebug "$PART1 not exist"
135 ventoy_false
136 return
137 fi
138
139 if ! [ -b $PART2 ]; then
140 vtdebug "$PART2 not exist"
141 ventoy_false
142 return
143 fi
144
145 PART1_TYPE=$(dd if=$DISK bs=1 count=1 skip=450 status=none | hexdump -n1 -e '1/1 "%02X"')
146 PART2_TYPE=$(dd if=$DISK bs=1 count=1 skip=466 status=none | hexdump -n1 -e '1/1 "%02X"')
147
148 # if [ "$PART1_TYPE" != "EE" ]; then
149 # if [ "$PART2_TYPE" != "EF" ]; then
150 # vtdebug "part2 type is $PART2_TYPE not EF"
151 # ventoy_false
152 # return
153 # fi
154 # fi
155
156 # PART1_TYPE=$(dd if=$DISK bs=1 count=1 skip=450 status=none | hexdump -n1 -e '1/1 "%02X"')
157 # if [ "$PART1_TYPE" != "07" ]; then
158 # vtdebug "part1 type is $PART2_TYPE not 07"
159 # ventoy_false
160 # return
161 # fi
162
163 if [ -e /sys/class/block/${PART1#/dev/}/start ]; then
164 PART1_START=$(cat /sys/class/block/${PART1#/dev/}/start)
165 fi
166
167 if [ "$PART1_START" != "2048" ]; then
168 vtdebug "part1 start is $PART1_START not 2048"
169 ventoy_false
170 return
171 fi
172
173 if [ "$VENTOY_SECTOR_NUM" != "$SIZE" ]; then
174 vtdebug "part2 size is $SIZE not $VENTOY_SECTOR_NUM"
175 ventoy_false
176 return
177 fi
178
179 ventoy_true
180 }
181
182 check_disk_secure_boot() {
183 if ! is_disk_contains_ventoy $1; then
184 ventoy_false
185 return
186 fi
187
188 PART2=$(get_disk_part_name $1 2)
189
190 vtoycli fat -s $PART2
191 }
192
193 get_disk_ventoy_version() {
194
195 if ! is_disk_contains_ventoy $1; then
196 ventoy_false
197 return
198 fi
199
200 PART2=$(get_disk_part_name $1 2)
201
202 ParseVer=$(vtoycli fat $PART2)
203 if [ $? -eq 0 ]; then
204 vtdebug "Ventoy version in $PART2 is $ParseVer"
205 echo $ParseVer
206 ventoy_true
207 return
208 fi
209
210 ventoy_false
211 }
212
213 wait_and_create_part() {
214 vPART1=$1
215 vPART2=$2
216 echo 'Wait for partitions $vPART1 and $vPART2 ...'
217 for i in 0 1 2 3 4 5 6 7 8 9; do
218 if ls -l $vPART1 2>/dev/null | grep -q '^b'; then
219 if ls -l $vPART2 2>/dev/null | grep -q '^b'; then
220 break
221 fi
222 else
223 echo "Wait for $vPART1 and $vPART2 ..."
224 sleep 1
225 fi
226 done
227
228 if ls -l $vPART1 2>/dev/null | grep -q '^b'; then
229 echo "$vPART1 exist OK"
230 else
231 MajorMinor=$(sed "s/:/ /" /sys/class/block/${vPART1#/dev/}/dev)
232 echo "mknod -m 0660 $vPART1 b $MajorMinor ..."
233 mknod -m 0660 $vPART1 b $MajorMinor
234 fi
235
236 if ls -l $vPART2 2>/dev/null | grep -q '^b'; then
237 echo "$vPART2 exist OK"
238 else
239 MajorMinor=$(sed "s/:/ /" /sys/class/block/${vPART2#/dev/}/dev)
240 echo "mknod -m 0660 $vPART2 b $MajorMinor ..."
241 mknod -m 0660 $vPART2 b $MajorMinor
242 fi
243
244 if ls -l $vPART1 2>/dev/null | grep -q '^b'; then
245 if ls -l $vPART2 2>/dev/null | grep -q '^b'; then
246 echo "partition exist OK"
247 fi
248 else
249 echo "[FAIL] $vPART1/$vPART2 does not exist"
250 exit 1
251 fi
252 }
253
254
255 format_ventoy_disk_mbr() {
256 reserve_mb=$1
257 DISK=$2
258 PARTTOOL=$3
259
260 PART1=$(get_disk_part_name $DISK 1)
261 PART2=$(get_disk_part_name $DISK 2)
262
263 sector_num=$(cat /sys/block/${DISK#/dev/}/size)
264
265 part1_start_sector=2048
266
267 if [ $reserve_mb -gt 0 ]; then
268 reserve_sector_num=$(expr $reserve_mb \* 2048)
269 part1_end_sector=$(expr $sector_num - $reserve_sector_num - $VENTOY_SECTOR_NUM - 1)
270 else
271 part1_end_sector=$(expr $sector_num - $VENTOY_SECTOR_NUM - 1)
272 fi
273
274 part2_start_sector=$(expr $part1_end_sector + 1)
275
276 modsector=$(expr $part2_start_sector % 8)
277 if [ $modsector -gt 0 ]; then
278 vtdebug "modsector:$modsector need to be aligned with 4KB"
279 part1_end_sector=$(expr $part1_end_sector - $modsector)
280 part2_start_sector=$(expr $part1_end_sector + 1)
281 fi
282
283 part2_end_sector=$(expr $part2_start_sector + $VENTOY_SECTOR_NUM - 1)
284
285 export part2_start_sector
286
287 vtdebug "part1_start_sector=$part1_start_sector part1_end_sector=$part1_end_sector"
288 vtdebug "part2_start_sector=$part2_start_sector part2_end_sector=$part2_end_sector"
289
290 if [ -e $PART1 ]; then
291 echo "delete $PART1"
292 rm -f $PART1
293 fi
294
295 if [ -e $PART2 ]; then
296 echo "delete $PART2"
297 rm -f $PART2
298 fi
299
300 echo ""
301 echo "Create partitions on $DISK by $PARTTOOL in MBR style ..."
302
303 if [ "$PARTTOOL" = "parted" ]; then
304 vtdebug "format disk by parted ..."
305 parted -a none --script $DISK \
306 mklabel msdos \
307 unit s \
308 mkpart primary ntfs $part1_start_sector $part1_end_sector \
309 mkpart primary fat16 $part2_start_sector $part2_end_sector \
310 set 1 boot on \
311 quit
312
313 sync
314 echo -en '\xEF' | dd of=$DISK conv=fsync bs=1 count=1 seek=466 > /dev/null 2>&1
315 else
316 vtdebug "format disk by fdisk ..."
317
318 fdisk $DISK >>./log.txt 2>&1 <<EOF
319 o
320 n
321 p
322 1
323 $part1_start_sector
324 $part1_end_sector
325 n
326 p
327 2
328 $part2_start_sector
329 $part2_end_sector
330 t
331 1
332 7
333 t
334 2
335 ef
336 a
337 1
338 w
339 EOF
340 fi
341
342 udevadm trigger --name-match=$DISK >/dev/null 2>&1
343 partprobe >/dev/null 2>&1
344 sleep 3
345 echo "Done"
346
347
348 echo 'Wait for partitions ...'
349 for i in 0 1 2 3 4 5 6 7 8 9; do
350 if [ -b $PART1 -a -b $PART2 ]; then
351 break
352 else
353 echo "Wait for $PART1/$PART2 ..."
354 sleep 1
355 fi
356 done
357
358 if ! [ -b $PART1 ]; then
359 MajorMinor=$(sed "s/:/ /" /sys/class/block/${PART1#/dev/}/dev)
360 echo "mknod -m 0660 $PART1 b $MajorMinor ..."
361 mknod -m 0660 $PART1 b $MajorMinor
362 fi
363
364 if ! [ -b $PART2 ]; then
365 MajorMinor=$(sed "s/:/ /" /sys/class/block/${PART2#/dev/}/dev)
366 echo "mknod -m 0660 $PART2 b $MajorMinor ..."
367 mknod -m 0660 $PART2 b $MajorMinor
368 fi
369
370 if [ -b $PART1 -a -b $PART2 ]; then
371 echo "partition exist OK"
372 else
373 echo "[FAIL] $PART1/$PART2 does not exist"
374 exit 1
375 fi
376
377 echo "create efi fat fs $PART2 ..."
378 for i in 0 1 2 3 4 5 6 7 8 9; do
379 check_umount_disk "$PART2"
380
381 if mkfs.vfat -F 16 -n VTOYEFI -s 1 $PART2; then
382 echo 'success'
383 break
384 else
385 echo "$? retry ..."
386 sleep 2
387 fi
388 done
389 }
390
391
392 format_ventoy_disk_gpt() {
393 reserve_mb=$1
394 DISK=$2
395 PARTTOOL=$3
396
397 PART1=$(get_disk_part_name $DISK 1)
398 PART2=$(get_disk_part_name $DISK 2)
399
400 sector_num=$(cat /sys/block/${DISK#/dev/}/size)
401
402 part1_start_sector=2048
403
404 if [ $reserve_mb -gt 0 ]; then
405 reserve_sector_num=$(expr $reserve_mb \* 2048 + 33)
406 part1_end_sector=$(expr $sector_num - $reserve_sector_num - $VENTOY_SECTOR_NUM - 1)
407 else
408 part1_end_sector=$(expr $sector_num - $VENTOY_SECTOR_NUM - 34)
409 fi
410
411 part2_start_sector=$(expr $part1_end_sector + 1)
412
413 modsector=$(expr $part2_start_sector % 8)
414 if [ $modsector -gt 0 ]; then
415 vtdebug "modsector:$modsector need to be aligned with 4KB"
416 part1_end_sector=$(expr $part1_end_sector - $modsector)
417 part2_start_sector=$(expr $part1_end_sector + 1)
418 fi
419
420 part2_end_sector=$(expr $part2_start_sector + $VENTOY_SECTOR_NUM - 1)
421
422 export part2_start_sector
423
424 vtdebug "part1_start_sector=$part1_start_sector part1_end_sector=$part1_end_sector"
425 vtdebug "part2_start_sector=$part2_start_sector part2_end_sector=$part2_end_sector"
426
427 if [ -e $PART1 ]; then
428 echo "delete $PART1"
429 rm -f $PART1
430 fi
431
432 if [ -e $PART2 ]; then
433 echo "delete $PART2"
434 rm -f $PART2
435 fi
436
437 echo ""
438 echo "Create partitions on $DISK by $PARTTOOL in GPT style ..."
439
440 vtdebug "format disk by parted ..."
441
442 if [ "$TOOLDIR" != "aarch64" ]; then
443 vt_set_efi_type="set 2 msftdata on"
444 fi
445
446 parted -a none --script $DISK \
447 mklabel gpt \
448 unit s \
449 mkpart Ventoy ntfs $part1_start_sector $part1_end_sector \
450 mkpart VTOYEFI fat16 $part2_start_sector $part2_end_sector \
451 $vt_set_efi_type \
452 quit
453
454 sync
455
456 vtoycli gpt -f $DISK
457 sync
458
459 udevadm trigger --name-match=$DISK >/dev/null 2>&1
460 partprobe >/dev/null 2>&1
461 sleep 3
462 echo "Done"
463
464 echo 'Wait for partitions ...'
465 for i in 0 1 2 3 4 5 6 7 8 9; do
466 if [ -b $PART1 -a -b $PART2 ]; then
467 break
468 else
469 echo "Wait for $PART1/$PART2 ..."
470 sleep 1
471 fi
472 done
473
474 if ! [ -b $PART1 ]; then
475 MajorMinor=$(sed "s/:/ /" /sys/class/block/${PART1#/dev/}/dev)
476 echo "mknod -m 0660 $PART1 b $MajorMinor ..."
477 mknod -m 0660 $PART1 b $MajorMinor
478 fi
479
480 if ! [ -b $PART2 ]; then
481 MajorMinor=$(sed "s/:/ /" /sys/class/block/${PART2#/dev/}/dev)
482 echo "mknod -m 0660 $PART2 b $MajorMinor ..."
483 mknod -m 0660 $PART2 b $MajorMinor
484 fi
485
486 if [ -b $PART1 -a -b $PART2 ]; then
487 echo "partition exist OK"
488 else
489 echo "[FAIL] $PART1/$PART2 does not exist"
490 exit 1
491 fi
492
493 echo "create efi fat fs $PART2 ..."
494
495 for i in 0 1 2 3 4 5 6 7 8 9; do
496 check_umount_disk "$PART2"
497
498 if mkfs.vfat -F 16 -n VTOYEFI -s 1 $PART2; then
499 echo 'success'
500 break
501 else
502 echo "$? retry ..."
503 sleep 2
504 fi
505 done
506 }
507
508
509
510
511