ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/pbcdedit/pbcdedit
(Generate patch)

Comparing pbcdedit/pbcdedit (file contents):
Revision 1.39 by root, Thu Aug 15 23:49:22 2019 UTC vs.
Revision 1.64 by root, Mon Aug 26 07:02:02 2019 UTC

19# along with this program. If not, see <https://www.gnu.org/licenses/>. 19# along with this program. If not, see <https://www.gnu.org/licenses/>.
20# 20#
21 21
22use 5.016; # numerous features need 5.14, __SUB__ needs 5.16 22use 5.016; # numerous features need 5.14, __SUB__ needs 5.16
23 23
24our $VERSION = '1.2'; 24our $VERSION = '1.4';
25our $JSON_VERSION = 2; # the version of the json objects generated by this program 25our $JSON_VERSION = 3; # the version of the json objects generated by this program
26 26
27our $CHANGELOG = <<EOF; 27our $CHANGELOG = <<EOF;
28
29 - work around lsblk bug sometimes giving dos pttype for gpt partitions.
30 - bootmenupolicy in synopsis must be set to 0 for text menu.
31
321.4 Thu Aug 22 10:48:22 CEST 2019
33 - new "create" subcommand.
34 - "create" and "edit" try to save and restore ownership/permissions
35 of bcd hives when writing the new file.
36 - editorial fixes to the documentation.
37 - add mininmal hive creation example.
38
391.3 Sat Aug 17 07:04:15 CEST 2019
40 - output of pbcdedit elements --json has changed, as it didn't
41 take the reorganisation by classes fully into account.
42 - json schema bumped to 3.
43 - new "bcd-device" and "bcd-legacy-device" subcommands.
44 - implement --json option for lsblk.
45
281.2 Fri Aug 16 00:20:41 CEST 2019 461.2 Fri Aug 16 00:20:41 CEST 2019
29 - bcde element names now depend on the bcd object type they are in, 47 - bcd element names now depend on the bcd object type they are in,
30 also affects "elements" output. 48 also affects "elements" output.
31 - json schema bumped to 2. 49 - json schema bumped to 2.
32 - new version command. 50 - new version command.
33 - numerous minor bugfixes. 51 - numerous minor bugfixes.
34 52
48 pbcdedit edit path/to/BCD edit-instructions... 66 pbcdedit edit path/to/BCD edit-instructions...
49 67
50 pbcdedit objects # list all supported object aliases and types 68 pbcdedit objects # list all supported object aliases and types
51 pbcdedit elements # list all supported bcd element aliases 69 pbcdedit elements # list all supported bcd element aliases
52 70
71 # Example: enable text-based boot menu.
72 pbcdedit edit /my/BCD set '{default}' bootmenupolicy 0
73
74 # Example change system device to first partition containing winload.
75 pbcdedit edit /my/BCD \
76 set '{default}' device 'locate=<null>,element,path' \
77 set '{default}' osdevice 'locate=<null>,element,path'
78
79
53=head1 DESCRIPTION 80=head1 DESCRIPTION
54 81
55This program allows you to create, read and modify Boot Configuration Data 82This program allows you to create, read and modify Boot Configuration Data
56(BCD) stores used by Windows Vista and newer versions of Windows. 83(BCD) stores used by Windows Vista and newer versions of Windows.
57 84
136=item C<parse> F<path> I<instructions...> 163=item C<parse> F<path> I<instructions...>
137 164
138Same as C<edit>, above, except it doesn't save the data store again. Can 165Same as C<edit>, above, except it doesn't save the data store again. Can
139be useful to extract some data from it. 166be useful to extract some data from it.
140 167
141=item C<lsblk> 168=item C<create> F<path> I<instructions...>
169
170Same as C<edit>, above, except it creates a new data store from scratch if
171needed. An existing store will be emptied completely.
172
173=item C<lsblk> [C<--json>]
142 174
143On a GNU/Linux system, you can get a list of partition device descriptors 175On a GNU/Linux system, you can get a list of partition device descriptors
144using this command - the external C<lsblk> command is required, as well as 176using this command - the external C<lsblk> command is required, as well as
145a mounted C</sys> file system. 177a mounted C</sys> file system.
146 178
147The output will be a list of all partitions in the system and C<partition> 179The output will be a list of all partitions in the system and C<partition>
148descriptors for GPT and both C<legacypartition> and C<partition> 180descriptors for GPT and both C<legacypartition> and C<partition>
149descriptors for MBR partitions. 181descriptors for MBR partitions.
182
183With C<--json> it will print similar information as C<lsblk --json>, but
184with extra C<bcd_device> and C<bcd_legacy_device> attributes.
185
186=item C<bcd-device> F<path>
187
188Tries to find the BCD device element for the given device, which currently
189must be a a partition of some kind. Prints the C<partition=> descriptor as
190a result, or nothing. Exit status will be true on success, and false on
191failure.
192
193Like C<lsblk>, above, this likely only works on GNU/Linux systems.
194
195Example: print the partition descriptor of tghe partition with label DATA.
196
197 $ pbcdedit bcd-device /dev/disk/by-label/DATA
198 partition=<null>,harddisk,mbr,47cbc08a,213579202560
199
200=item C<bcd-legacy-device> F<path>
201
202Like above, but uses a C<legacypartition> descriptor instead.
150 203
151=item C<objects> [C<--json>] 204=item C<objects> [C<--json>]
152 205
153Outputs two tables: a table listing all type aliases with their hex BCD 206Outputs two tables: a table listing all type aliases with their hex BCD
154element ID, and all object name aliases with their GUID and default type 207element ID, and all object name aliases with their GUID and default type
256 309
257Note that minimal doesn't mean recommended - Windows itself will add stuff 310Note that minimal doesn't mean recommended - Windows itself will add stuff
258to this during or after boot, and you might or might not run into issues 311to this during or after boot, and you might or might not run into issues
259when installing updates as it might not be able to find the F<bootmgr>. 312when installing updates as it might not be able to find the F<bootmgr>.
260 313
314This is how you would create a minimal hive with PBCDEDIT from within
315GNU/Linux, assuming F</dev/sdc3> is the windows partition, using
316a random GUID for the osloader and using C<partition> instead of
317C<legacypartition>:
318
319 osldr="{$(uuidgen)}"
320 part=$(pbcdedit bcd-device /dev/sdc3)
321 pbcdedit create minimal.bcd \
322 set '{bootmgr}' default "$osldr" \
323 set "$osldr" type application::osloader \
324 set "$osldr" description 'Windows Boot' \
325 set "$osldr" device "$part" \
326 set "$osldr" osdevice "$part" \
327 set "$osldr" path '\Windows\system32\winload.exe' \
328 set "$osldr" systemroot '\Windows'
329
261=head2 The C<meta> key 330=head2 The C<meta> key
262 331
263The C<meta> key is not stored in the BCD data store but is used only 332The C<meta> key is not stored in the BCD data store but is used only
264by PBCDEDIT. It is always generated when exporting, and importing will 333by PBCDEDIT. It is always generated when exporting, and importing will
265be refused when it exists and the version stored inside doesn't store 334be refused when it exists and the version stored inside doesn't store
352 421
353 "displaybootmenu" : 0, 422 "displaybootmenu" : 0,
354 423
355=item integer 424=item integer
356 425
357Again, very simple, this is a 64 bit integer. IT can be either specified 426Again, very simple, this is a 64 bit integer. It can be either specified
358as a decimal number, as a hex number (by prefixing it with C<0x>) or as a 427as a decimal number, as a hex number (by prefixing it with C<0x>) or as a
359binary number (prefix C<0b>). 428binary number (prefix C<0b>).
360 429
361For example, the boot C<timeout> is an integer, specifying the automatic 430For example, the boot C<timeout> is an integer, specifying the automatic
362boot delay in seconds: 431boot delay in seconds:
364 "timeout" : 30, 433 "timeout" : 30,
365 434
366=item integer list 435=item integer list
367 436
368This is a list of 64 bit integers separated by whitespace. It is not used 437This is a list of 64 bit integers separated by whitespace. It is not used
369much, so here is a somewhat artificial an untested example of using 438much, so here is a somewhat artificial and untested example of using
370C<customactions> to specify a certain custom, eh, action to be executed 439C<customactions> to specify a certain custom, eh, action to be executed
371when pressing C<F10> at boot: 440when pressing C<F10> at boot:
372 441
373 "customactions" : "0x1000044000001 0x54000001", 442 "customactions" : "0x1000044000001 0x54000001",
374 443
402This type is why I write I<most> are easy to explain earlier: This type 471This type is why I write I<most> are easy to explain earlier: This type
403is the pinnacle of Microsoft-typical hacks layered on top of other 472is the pinnacle of Microsoft-typical hacks layered on top of other
404hacks. Understanding this type took more time than writing all the rest of 473hacks. Understanding this type took more time than writing all the rest of
405PBCDEDIT, and because it is so complex, this type has its own subsection 474PBCDEDIT, and because it is so complex, this type has its own subsection
406below. 475below.
476
407=back 477=back
408 478
409=head4 The BCD "device" element type 479=head3 The BCD "device" element type
410 480
411Device elements specify, well, devices. They are used for such diverse 481Device elements specify, well, devices. They are used for such diverse
412purposes such as finding a TFTP network boot image, serial ports or VMBUS 482purposes such as finding a TFTP network boot image, serial ports or VMBUS
413devices, but most commonly they are used to specify the disk (harddisk, 483devices, but most commonly they are used to specify the disk (harddisk,
414cdrom, ramdisk, vhd...) to boot from. 484cdrom, ramdisk, vhd...) to boot from.
422element, so almost everything known about it had to be researched first 492element, so almost everything known about it had to be researched first
423in the process of writing this script, and consequently, support for BCD 493in the process of writing this script, and consequently, support for BCD
424device elements is partial only. 494device elements is partial only.
425 495
426On the other hand, the expressive power of PBCDEDIT in specifying devices 496On the other hand, the expressive power of PBCDEDIT in specifying devices
427is much bigger than BCDEDIT and therefore more can be done with it. The 497is much greater than BCDEDIT and therefore more can be done with it. The
428downside is that BCD device elements are much more complicated than what 498downside is that BCD device elements are much more complicated than what
429you might think from reading the BCDEDIT documentation. 499you might think from reading the BCDEDIT documentation.
430 500
431In other words, simple things are complicated, and complicated things are 501In other words, simple things are complicated, and complicated things are
432possible. 502possible.
475the leading GUID, which it can always decode). In such cases, it will 545the leading GUID, which it can always decode). In such cases, it will
476convert the device into this type with a hexdump of the element data. 546convert the device into this type with a hexdump of the element data.
477 547
478=item C<null> 548=item C<null>
479 549
480This is another special type - sometimes, a device all zero-filled, which 550This is another special type - sometimes, a device is all zero-filled,
481is not valid. This can mark the absence of a device or something PBCDEDIT 551which is not valid. This can mark the absence of a device or something
482does not understand, so it decodes it into this special "all zero" type 552PBCDEDIT does not understand, so it decodes it into this special "all
483called C<null>. 553zero" type called C<null>.
484 554
485It's most commonly found in devices that can use an optional parent 555It's most commonly found in devices that can use an optional parent
486device, when no parent device is used. 556device, when no parent device is used.
487 557
488=item C<boot> 558=item C<boot>
599 669
600Last not least, the most complex type, C<block>, which... specifies block 670Last not least, the most complex type, C<block>, which... specifies block
601devices (which could be inside a F<vhdx> file for example). 671devices (which could be inside a F<vhdx> file for example).
602 672
603I<devicetypes> is one of C<harddisk>, C<floppy>, C<cdrom>, C<ramdisk>, 673I<devicetypes> is one of C<harddisk>, C<floppy>, C<cdrom>, C<ramdisk>,
604C<file> or C<vhd> - the same as for C<partiion=>. 674C<file> or C<vhd> - the same as for C<partition=>.
605 675
606The remaining arguments change depending on the I<devicetype>: 676The remaining arguments change depending on the I<devicetype>:
607 677
608=over 678=over
609 679
639 709
640Probably not yet implemented. Tell me of your needs... 710Probably not yet implemented. Tell me of your needs...
641 711
642=back 712=back
643 713
644=back5 Examples 714=head4 Examples
645 715
646This concludes the syntax overview for device elements, but probably 716This concludes the syntax overview for device elements, but probably
647leaves many questions open. I can't help with most of them, as I also ave 717leaves many questions open. I can't help with most of them, as I also have
648many questions, but I can walk you through some actual examples using more 718many questions, but I can walk you through some actual examples using more
649complex aspects. 719complex aspects.
650 720
651=item C<< locate=<block=vhd,<block=file,<locate=<null>,path,\disk.vhdx>,\disk.vhdx>>,element,path >> 721=item C<< locate=<block=vhd,<block=file,<locate=<null>,path,\disk.vhdx>,\disk.vhdx>>,element,path >>
652 722
866sub xxd($$) { 936sub xxd($$) {
867 open my $xxd, "| xxd | sed -e 's/^/\Q$_[0]\E: /'"; 937 open my $xxd, "| xxd | sed -e 's/^/\Q$_[0]\E: /'";
868 syswrite $xxd, $_[1]; 938 syswrite $xxd, $_[1];
869} 939}
870 940
941# get some meta info on a file (uid, gid, perms)
942sub stat_get($) {
943 [(stat shift)[4, 5, 2]]
944}
945
946# set stat info on a file
947sub stat_set($$) {
948 my ($fh_or_path, $stat) = @_;
949
950 return unless $stat;
951 chown $stat->[0], $stat->[1], $fh_or_path;
952 chmod +($stat->[2] & 07777), $fh_or_path;
953}
954
871sub file_load($) { 955sub file_load($) {
872 my ($path) = @_; 956 my ($path) = @_;
873 957
874 open my $fh, "<:raw", $path 958 open my $fh, "<:raw", $path
875 or die "$path: $!\n"; 959 or die "$path: $!\n";
876 my $size = -s $fh; 960 my $size = -s $fh;
877 $size = read $fh, my $buf, $size 961 $size = read $fh, my $buf, $size
878 or die "$path: short read\n"; 962 or die "$path: short read\n";
879 963
880 $buf 964 $buf
965}
966
967sub file_save($$;$) {
968 my ($path, $data, $stat) = @_;
969
970 open my $fh, ">:raw", "$path~"
971 or die "$path~: $!\n";
972 print $fh $data
973 or die "$path~: short write\n";
974 stat_set $fh, $stat;
975 $fh->sync;
976 close $fh;
977
978 rename "$path~", $path;
881} 979}
882 980
883# sources and resources used for writing pbcdedit 981# sources and resources used for writing pbcdedit
884# 982#
885# registry: 983# registry:
1071 my ($rname, $root) = $decode_key->($rootcell); 1169 my ($rname, $root) = $decode_key->($rootcell);
1072 1170
1073 [$rname, $root] 1171 [$rname, $root]
1074} 1172}
1075 1173
1076# return a binary windows fILETIME struct 1174# return a binary windows FILETIME struct
1077sub filetime_now { 1175sub filetime_now {
1078 my ($s, $ms) = Time::HiRes::gettimeofday; 1176 my ($s, $ms) = Time::HiRes::gettimeofday;
1079 1177
1080 pack "Q<", $s = ($s * 1_000_000 + $ms) * 10 + 116_444_736_000_000_000 1178 pack "Q<", ($s * 1_000_000 + $ms) * 10
1179 + 116_444_736_000_000_000 # 1970-01-01 00:00:00
1081} 1180}
1082 1181
1083# encode a registry hive 1182# encode a registry hive
1084sub regf_encode($) { 1183sub regf_encode($) {
1085 my ($hive) = @_; 1184 my ($hive) = @_;
1242 1341
1243 regf_decode file_load $path 1342 regf_decode file_load $path
1244} 1343}
1245 1344
1246# encode and save registry to file 1345# encode and save registry to file
1247sub regf_save { 1346sub regf_save($$;$) {
1248 my ($path, $hive) = @_; 1347 my ($path, $hive, $stat) = @_;
1249 1348
1250 $hive = regf_encode $hive; 1349 $hive = regf_encode $hive;
1251 1350
1252 open my $regf, ">:raw", "$path~" 1351 file_save $path, $hive, $stat;
1253 or die "$path~: $!\n";
1254 print $regf $hive
1255 or die "$path~: short write\n";
1256 $regf->sync;
1257 close $regf;
1258
1259 rename "$path~", $path;
1260} 1352}
1261 1353
1262############################################################################# 1354#############################################################################
1263# bcd stuff 1355# bcd stuff
1264 1356
2199 or die "$_: malformed or missing vmbus interface instance guid\n"; 2291 or die "$_: malformed or missing vmbus interface instance guid\n";
2200 my $instance = enc_guid $1; 2292 my $instance = enc_guid $1;
2201 2293
2202 $payload = pack "a16a16x24", $type, $instance; 2294 $payload = pack "a16a16x24", $type, $instance;
2203 2295
2296# } elsif ($type eq "udp") {
2297# $payload = pack "Va16", 1, "12345678";
2298
2204 } else { 2299 } else {
2205 die "$type: not a supported device type (binary, null, boot, legacypartition, partition, block, locate)\n"; 2300 die "$type: not a supported device type (binary, null, boot, legacypartition, partition, block, locate)\n";
2206 } 2301 }
2207 2302
2208 return ( 2303 return (
2390 } 2485 }
2391 2486
2392} 2487}
2393 2488
2394############################################################################# 2489#############################################################################
2395# command line parser 2490# other utilities
2396 2491
2397# json to stdout 2492# json to stdout
2398sub prjson($) { 2493sub prjson($) {
2399 print $json_coder->encode ($_[0]); 2494 print $json_coder->encode ($_[0]);
2400} 2495}
2404 my $json; 2499 my $json;
2405 1 while read STDIN, $json, 65536, length $json; 2500 1 while read STDIN, $json, 65536, length $json;
2406 $json_coder->decode ($json) 2501 $json_coder->decode ($json)
2407} 2502}
2408 2503
2409# all subcommands 2504sub lsblk() {
2505 my $lsblk = $json_coder->decode (scalar qx<lsblk --json -o PATH,KNAME,MAJ:MIN,TYPE,PTTYPE,PTUUID,PARTUUID,LABEL,FSTYPE>);
2506
2507 for my $dev (@{ $lsblk->{blockdevices} }) {
2508 if ($dev->{type} eq "part") {
2509
2510 # lsblk sometimes gives a bogus pttype, so we recreate it here
2511 $dev->{pttype} = $dev->{ptuuid} =~ /^$RE_GUID\z/
2512 ? "gpt" : "dos";
2513
2514 if ($dev->{pttype} eq "gpt") {
2515 $dev->{bcd_device} = "partition=<null>,harddisk,gpt,$dev->{ptuuid},$dev->{partuuid}";
2516 } elsif ($dev->{pttype} eq "dos") { # why not "mbr" :(
2517 if ($dev->{partuuid} =~ /^([0-9a-f]{8})-([0-9a-f]{2})\z/i) {
2518 my ($diskid, $partno) = ($1, hex $2);
2519 $dev->{bcd_legacy_device} = "legacypartition=<null>,harddisk,mbr,$diskid,$partno";
2520 if (open my $fh, "/sys/class/block/$dev->{kname}/start") {
2521 my $start = 512 * readline $fh;
2522 $dev->{bcd_device} = "partition=<null>,harddisk,mbr,$diskid,$start";
2523 }
2524 }
2525 }
2526 }
2527 }
2528
2529 $lsblk->{blockdevices}
2530}
2531
2532sub prdev($$) {
2533 my ($path, $attribute) = @_;
2534
2535 # rather than stat'ing and guessing how devices are encoded, we use lsblk for this
2536 my $mm = $json_coder->decode (scalar qx<lsblk -d -o MAJ:MIN -J \Q$path\E>)->{blockdevices}[0]{"maj:min"};
2537
2538 my $lsblk = lsblk;
2539
2540 for my $dev (@$lsblk) {
2541 if ($dev->{"maj:min"} eq $mm && $dev->{$attribute}) {
2542 say $dev->{$attribute};
2543 exit 0;
2544 }
2545 }
2546
2547 exit 1;
2548}
2549
2550#############################################################################
2551# command line parser
2552
2410our %CMD = ( 2553our %CMD = (
2411 help => sub { 2554 help => sub {
2412 require Pod::Usage; 2555 require Pod::Usage;
2413 Pod::Usage::pod2usage (-verbose => 2); 2556 Pod::Usage::pod2usage (-verbose => 2);
2414 }, 2557 },
2465 BCDE_FORMAT_INTEGER , "integer", 2608 BCDE_FORMAT_INTEGER , "integer",
2466 BCDE_FORMAT_BOOLEAN , "boolean", 2609 BCDE_FORMAT_BOOLEAN , "boolean",
2467 BCDE_FORMAT_INTEGER_LIST, "integer list", 2610 BCDE_FORMAT_INTEGER_LIST, "integer list",
2468 ); 2611 );
2469 2612
2470 my %element; 2613 my @element;
2471 2614
2472 for my $class (sort keys %rbcde_byclass) { 2615 for my $class (sort keys %rbcde_byclass) {
2473 my $rbcde = $rbcde_byclass{$class}; 2616 my $rbcde = $rbcde_byclass{$class};
2474 2617
2475 unless ($json) { 2618 unless ($json) {
2478 printf "%-9s %-12s %s\n", "Element", "Format", "Name Alias"; 2621 printf "%-9s %-12s %s\n", "Element", "Format", "Name Alias";
2479 } 2622 }
2480 for my $name (sort keys %$rbcde) { 2623 for my $name (sort keys %$rbcde) {
2481 my $id = $rbcde->{$name}; 2624 my $id = $rbcde->{$name};
2482 my $format = $format_name{$id & BCDE_FORMAT}; 2625 my $format = $format_name{$id & BCDE_FORMAT};
2483 $id = sprintf "%08x", $id;
2484 2626
2485 if ($json) { 2627 if ($json) {
2486 $element{$id} = [$class, $format, $name]; 2628 push @element, [$class, $id * 1, $format, $name];
2487 } else { 2629 } else {
2630 $id = sprintf "%08x", $id;
2488 printf "%-9s %-12s %s\n", $id, $format, $name; 2631 printf "%-9s %-12s %s\n", $id, $format, $name;
2489 } 2632 }
2490 } 2633 }
2491 } 2634 }
2492 print "\n" unless $json; 2635 print "\n" unless $json;
2493 2636
2494 prjson { 2637 prjson {
2495 version => $JSON_VERSION, 2638 version => $JSON_VERSION,
2496 element => \%element, 2639 element => \@element,
2497 class => \@bcde_typeclass, 2640 class => \@bcde_typeclass,
2498 } if $json; 2641 } if $json;
2499 2642
2500 }, 2643 },
2501 2644
2505 2648
2506 import => sub { 2649 import => sub {
2507 regf_save shift, bcd_encode rdjson; 2650 regf_save shift, bcd_encode rdjson;
2508 }, 2651 },
2509 2652
2653 create => sub {
2654 my $path = shift;
2655 my $stat = stat_get $path; # should actually be done at file load time
2656 my $bcd = { };
2657 bcd_edit $path, $bcd, @_;
2658 regf_save $path, bcd_encode $bcd;
2659 stat_set $path, $stat;
2660 },
2661
2510 edit => sub { 2662 edit => sub {
2511 my $path = shift; 2663 my $path = shift;
2664 my $stat = stat_get $path; # should actually be done at file load time
2512 my $bcd = bcd_decode regf_load $path; 2665 my $bcd = bcd_decode regf_load $path;
2513 bcd_edit $path, $bcd, @_; 2666 bcd_edit $path, $bcd, @_;
2514 regf_save $path, bcd_encode $bcd; 2667 regf_save $path, bcd_encode $bcd;
2668 stat_set $path, $stat;
2515 }, 2669 },
2516 2670
2517 parse => sub { 2671 parse => sub {
2518 my $path = shift; 2672 my $path = shift;
2519 my $bcd = bcd_decode regf_load $path; 2673 my $bcd = bcd_decode regf_load $path;
2528 "import-regf" => sub { 2682 "import-regf" => sub {
2529 regf_save shift, rdjson; 2683 regf_save shift, rdjson;
2530 }, 2684 },
2531 2685
2532 lsblk => sub { 2686 lsblk => sub {
2687 my $json = $_[0] eq "--json";
2688
2689 my $lsblk = lsblk;
2690
2691 if ($json) {
2692 prjson $lsblk;
2693 } else {
2533 printf "%-10s %-8.8s %-6.6s %-3s %s\n", "DEVICE", "LABEL", "FSTYPE", "PT", "DEVICE DESCRIPTOR"; 2694 printf "%-10s %-8.8s %-6.6s %-3s %s\n", "DEVICE", "LABEL", "FSTYPE", "PT", "DEVICE DESCRIPTOR";
2534 2695 for my $dev (@$lsblk) {
2535 my $lsblk = $json_coder->decode (scalar qx<lsblk --json -o PATH,KNAME,TYPE,PTTYPE,PTUUID,PARTUUID,LABEL,FSTYPE>); 2696 for my $bcd ($dev->{bcd_device}, $dev->{bcd_legacy_device}) {
2536
2537 for my $dev (@{ $lsblk->{blockdevices} }) {
2538 my $pr = sub {
2539 printf "%-10s %-8.8s %-6.6s %-3s %s\n", 2697 printf "%-10s %-8.8s %-6.6s %-3s %s\n",
2540 $dev->{path}, $dev->{label}, $dev->{fstype}, $dev->{pttype}, $_[0]; 2698 $dev->{path}, $dev->{label}, $dev->{fstype}, $dev->{pttype}, $bcd
2541 };
2542
2543 if ($dev->{type} eq "part") {
2544 if ($dev->{pttype} eq "gpt") {
2545 $pr->("partition=<null>,harddisk,gpt,$dev->{ptuuid},$dev->{partuuid}");
2546 } elsif ($dev->{pttype} eq "dos") { # why not "mbr" :(
2547 if ($dev->{partuuid} =~ /^([0-9a-f]{8})-([0-9a-f]{2})\z/i) {
2548 my ($diskid, $partno) = ($1, hex $2);
2549 $pr->("legacypartition=<null>,harddisk,mbr,$diskid,$partno");
2550 if (open my $fh, "/sys/class/block/$dev->{kname}/start") {
2551 my $start = 512 * readline $fh;
2552 $pr->("partition=<null>,harddisk,mbr,$diskid,$start");
2553 } 2699 if $bcd;
2554 }
2555 } 2700 }
2556 } 2701 }
2557 } 2702 }
2703 },
2704
2705 "bcd-device" => sub {
2706 prdev shift, "bcd_device";
2707 },
2708
2709 "bcd-legacy-device" => sub {
2710 prdev shift, "bcd_legacy_device";
2558 }, 2711 },
2559 2712
2560 version => sub { 2713 version => sub {
2561 print "\n", 2714 print "\n",
2562 "PBCDEDIT version $VERSION, copyright 2019 Marc A. Lehmann <pbcdedit\@schmorp.de>.\n", 2715 "PBCDEDIT version $VERSION, copyright 2019 Marc A. Lehmann <pbcdedit\@schmorp.de>.\n",

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines