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