… | |
… | |
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 | |
22 | use 5.016; # numerous features need 5.14, __SUB__ needs 5.16 |
22 | use 5.016; # numerous features need 5.14, __SUB__ needs 5.16 |
23 | |
23 | |
24 | our $VERSION = '1.1'; |
24 | our $VERSION = '1.2'; |
25 | our $JSON_VERSION = 1; # the versiobn of the json objects generated by this program |
25 | our $JSON_VERSION = 2; # the version of the json objects generated by this program |
|
|
26 | |
|
|
27 | our $CHANGELOG = <<EOF; |
|
|
28 | 1.2 Fri Aug 16 00:20:41 CEST 2019 |
|
|
29 | - bcde element names now depend on the bcd object type they are in, |
|
|
30 | also affects "elements" output. |
|
|
31 | - json schema bumped to 2. |
|
|
32 | - new version command. |
|
|
33 | - numerous minor bugfixes. |
|
|
34 | |
|
|
35 | EOF |
26 | |
36 | |
27 | =head1 NAME |
37 | =head1 NAME |
28 | |
38 | |
29 | pbcdedit - portable boot configuration data (BCD) store editor |
39 | pbcdedit - portable boot configuration data (BCD) store editor |
30 | |
40 | |
31 | =head1 SYNOPSIS |
41 | =head1 SYNOPSIS |
32 | |
42 | |
33 | pbcdedit help # output manual page |
43 | pbcdedit help # output manual page |
|
|
44 | pbcdedit version # output version and changelog |
34 | |
45 | |
35 | pbcdedit export path/to/BCD # output BCD hive as JSON |
46 | pbcdedit export path/to/BCD # output BCD hive as JSON |
36 | pbcdedit import path/to/BCD # convert standard input to BCD hive |
47 | pbcdedit import path/to/BCD # convert standard input to BCD hive |
37 | pbcdedit edit path/to/BCD edit-instructions... |
48 | pbcdedit edit path/to/BCD edit-instructions... |
38 | |
49 | |
… | |
… | |
91 | =over |
102 | =over |
92 | |
103 | |
93 | =item C<help> |
104 | =item C<help> |
94 | |
105 | |
95 | Displays the whole manual page (this document). |
106 | Displays the whole manual page (this document). |
|
|
107 | |
|
|
108 | =item C<version> |
|
|
109 | |
|
|
110 | This outputs the PBCDEDIT version, the JSON schema version it uses and the |
|
|
111 | full log of changes. |
96 | |
112 | |
97 | =item C<export> F<path> |
113 | =item C<export> F<path> |
98 | |
114 | |
99 | Reads a BCD data store and writes a JSON representation of it to standard |
115 | Reads a BCD data store and writes a JSON representation of it to standard |
100 | output. |
116 | output. |
… | |
… | |
827 | =cut |
843 | =cut |
828 | |
844 | |
829 | # common sense is optional, but recommended |
845 | # common sense is optional, but recommended |
830 | BEGIN { eval { require "common/sense.pm"; } && common::sense->import } |
846 | BEGIN { eval { require "common/sense.pm"; } && common::sense->import } |
831 | |
847 | |
|
|
848 | no warnings 'portable'; # avoid 32 bit integer warnings |
|
|
849 | |
832 | use Encode (); |
850 | use Encode (); |
833 | use List::Util (); |
851 | use List::Util (); |
834 | use IO::Handle (); |
852 | use IO::Handle (); |
835 | use Time::HiRes (); |
853 | use Time::HiRes (); |
836 | |
854 | |
… | |
… | |
1358 | sub BCDE_FORMAT_GUID_LIST () { 0x04000000 } |
1376 | sub BCDE_FORMAT_GUID_LIST () { 0x04000000 } |
1359 | sub BCDE_FORMAT_INTEGER () { 0x05000000 } |
1377 | sub BCDE_FORMAT_INTEGER () { 0x05000000 } |
1360 | sub BCDE_FORMAT_BOOLEAN () { 0x06000000 } |
1378 | sub BCDE_FORMAT_BOOLEAN () { 0x06000000 } |
1361 | sub BCDE_FORMAT_INTEGER_LIST () { 0x07000000 } |
1379 | sub BCDE_FORMAT_INTEGER_LIST () { 0x07000000 } |
1362 | |
1380 | |
1363 | sub dec_device; |
|
|
1364 | sub enc_device; |
|
|
1365 | |
|
|
1366 | sub enc_integer($) { |
1381 | sub enc_integer($) { |
1367 | no warnings 'portable'; # ugh |
|
|
1368 | my $value = shift; |
1382 | my $value = shift; |
1369 | $value = oct $value if $value =~ /^0[bBxX]/; |
1383 | $value = oct $value if $value =~ /^0[bBxX]/; |
1370 | unpack "H*", pack "Q<", $value |
1384 | unpack "H*", pack "Q<", $value |
1371 | } |
1385 | } |
|
|
1386 | |
|
|
1387 | sub enc_device($$); |
|
|
1388 | sub dec_device($$); |
1372 | |
1389 | |
1373 | our %bcde_dec = ( |
1390 | our %bcde_dec = ( |
1374 | BCDE_FORMAT_DEVICE , \&dec_device, |
1391 | BCDE_FORMAT_DEVICE , \&dec_device, |
1375 | # # for round-trip verification |
1392 | # # for round-trip verification |
1376 | # BCDE_FORMAT_DEVICE , sub { |
1393 | # BCDE_FORMAT_DEVICE , sub { |
… | |
… | |
1386 | BCDE_FORMAT_BOOLEAN , sub { shift eq "00" ? 0 : 1 }, |
1403 | BCDE_FORMAT_BOOLEAN , sub { shift eq "00" ? 0 : 1 }, |
1387 | BCDE_FORMAT_INTEGER_LIST, sub { join " ", unpack "Q*", pack "H*", shift }, # not sure if this cna be 4 bytes |
1404 | BCDE_FORMAT_INTEGER_LIST, sub { join " ", unpack "Q*", pack "H*", shift }, # not sure if this cna be 4 bytes |
1388 | ); |
1405 | ); |
1389 | |
1406 | |
1390 | our %bcde_enc = ( |
1407 | our %bcde_enc = ( |
1391 | BCDE_FORMAT_DEVICE , sub { binary => enc_device shift }, |
1408 | BCDE_FORMAT_DEVICE , sub { binary => enc_device $_[0], $_[1] }, |
1392 | BCDE_FORMAT_STRING , sub { sz => shift }, |
1409 | BCDE_FORMAT_STRING , sub { sz => shift }, |
1393 | BCDE_FORMAT_GUID , sub { sz => "{" . (dec_guid enc_wguid shift) . "}" }, |
1410 | BCDE_FORMAT_GUID , sub { sz => "{" . (dec_guid enc_wguid shift) . "}" }, |
1394 | BCDE_FORMAT_GUID_LIST , sub { multi_sz => [map "{" . (dec_guid enc_wguid $_) . "}", split /\s+/, shift ] }, |
1411 | BCDE_FORMAT_GUID_LIST , sub { multi_sz => [map "{" . (dec_guid enc_wguid $_) . "}", split /\s+/, shift ] }, |
1395 | BCDE_FORMAT_INTEGER , sub { binary => enc_integer shift }, |
1412 | BCDE_FORMAT_INTEGER , sub { binary => enc_integer shift }, |
1396 | BCDE_FORMAT_BOOLEAN , sub { binary => shift ? "01" : "00" }, |
1413 | BCDE_FORMAT_BOOLEAN , sub { binary => shift ? "01" : "00" }, |
1397 | BCDE_FORMAT_INTEGER_LIST, sub { binary => join "", map enc_integer $_, split /\s+/, shift }, |
1414 | BCDE_FORMAT_INTEGER_LIST, sub { binary => join "", map enc_integer $_, split /\s+/, shift }, |
1398 | ); |
1415 | ); |
1399 | |
1416 | |
1400 | # BCD Elements |
1417 | # BCD Elements |
1401 | our %bcde = ( |
1418 | our %bcde_byclass = ( |
|
|
1419 | any => { |
1402 | 0x11000001 => 'device', |
1420 | 0x11000001 => 'device', |
1403 | 0x12000002 => 'path', |
1421 | 0x12000002 => 'path', |
1404 | 0x12000004 => 'description', |
1422 | 0x12000004 => 'description', |
1405 | 0x12000005 => 'locale', |
1423 | 0x12000005 => 'locale', |
1406 | 0x14000006 => 'inherit', |
1424 | 0x14000006 => 'inherit', |
1407 | 0x15000007 => 'truncatememory', |
1425 | 0x15000007 => 'truncatememory', |
1408 | 0x14000008 => 'recoverysequence', |
1426 | 0x14000008 => 'recoverysequence', |
1409 | 0x16000009 => 'recoveryenabled', |
1427 | 0x16000009 => 'recoveryenabled', |
1410 | 0x1700000a => 'badmemorylist', |
1428 | 0x1700000a => 'badmemorylist', |
1411 | 0x1600000b => 'badmemoryaccess', |
1429 | 0x1600000b => 'badmemoryaccess', |
1412 | 0x1500000c => 'firstmegabytepolicy', |
1430 | 0x1500000c => 'firstmegabytepolicy', |
1413 | 0x1500000d => 'relocatephysical', |
1431 | 0x1500000d => 'relocatephysical', |
1414 | 0x1500000e => 'avoidlowmemory', |
1432 | 0x1500000e => 'avoidlowmemory', |
1415 | 0x1600000f => 'traditionalkseg', |
1433 | 0x1600000f => 'traditionalkseg', |
1416 | 0x16000010 => 'bootdebug', |
1434 | 0x16000010 => 'bootdebug', |
1417 | 0x15000011 => 'debugtype', |
1435 | 0x15000011 => 'debugtype', |
1418 | 0x15000012 => 'debugaddress', |
1436 | 0x15000012 => 'debugaddress', |
1419 | 0x15000013 => 'debugport', |
1437 | 0x15000013 => 'debugport', |
1420 | 0x15000014 => 'baudrate', |
1438 | 0x15000014 => 'baudrate', |
1421 | 0x15000015 => 'channel', |
1439 | 0x15000015 => 'channel', |
1422 | 0x12000016 => 'targetname', |
1440 | 0x12000016 => 'targetname', |
1423 | 0x16000017 => 'noumex', |
1441 | 0x16000017 => 'noumex', |
1424 | 0x15000018 => 'debugstart', |
1442 | 0x15000018 => 'debugstart', |
1425 | 0x12000019 => 'busparams', |
1443 | 0x12000019 => 'busparams', |
1426 | 0x1500001a => 'hostip', |
1444 | 0x1500001a => 'hostip', |
1427 | 0x1500001b => 'port', |
1445 | 0x1500001b => 'port', |
1428 | 0x1600001c => 'dhcp', |
1446 | 0x1600001c => 'dhcp', |
1429 | 0x1200001d => 'key', |
1447 | 0x1200001d => 'key', |
1430 | 0x1600001e => 'vm', |
1448 | 0x1600001e => 'vm', |
1431 | 0x16000020 => 'bootems', |
1449 | 0x16000020 => 'bootems', |
1432 | 0x15000022 => 'emsport', |
1450 | 0x15000022 => 'emsport', |
1433 | 0x15000023 => 'emsbaudrate', |
1451 | 0x15000023 => 'emsbaudrate', |
1434 | 0x12000030 => 'loadoptions', |
1452 | 0x12000030 => 'loadoptions', |
1435 | 0x16000040 => 'advancedoptions', |
1453 | 0x16000040 => 'advancedoptions', |
1436 | 0x16000041 => 'optionsedit', |
1454 | 0x16000041 => 'optionsedit', |
1437 | 0x15000042 => 'keyringaddress', |
1455 | 0x15000042 => 'keyringaddress', |
1438 | 0x11000043 => 'bootstatdevice', |
1456 | 0x11000043 => 'bootstatdevice', |
1439 | 0x12000044 => 'bootstatfilepath', |
1457 | 0x12000044 => 'bootstatfilepath', |
1440 | 0x16000045 => 'preservebootstat', |
1458 | 0x16000045 => 'preservebootstat', |
1441 | 0x16000046 => 'graphicsmodedisabled', |
1459 | 0x16000046 => 'graphicsmodedisabled', |
1442 | 0x15000047 => 'configaccesspolicy', |
1460 | 0x15000047 => 'configaccesspolicy', |
1443 | 0x16000048 => 'nointegritychecks', |
1461 | 0x16000048 => 'nointegritychecks', |
1444 | 0x16000049 => 'testsigning', |
1462 | 0x16000049 => 'testsigning', |
1445 | 0x1200004a => 'fontpath', |
1463 | 0x1200004a => 'fontpath', |
1446 | 0x1500004b => 'integrityservices', |
1464 | 0x1500004b => 'integrityservices', |
1447 | 0x1500004c => 'volumebandid', |
1465 | 0x1500004c => 'volumebandid', |
1448 | 0x16000050 => 'extendedinput', |
1466 | 0x16000050 => 'extendedinput', |
1449 | 0x15000051 => 'initialconsoleinput', |
1467 | 0x15000051 => 'initialconsoleinput', |
1450 | 0x15000052 => 'graphicsresolution', |
1468 | 0x15000052 => 'graphicsresolution', |
1451 | 0x16000053 => 'restartonfailure', |
1469 | 0x16000053 => 'restartonfailure', |
1452 | 0x16000054 => 'highestmode', |
1470 | 0x16000054 => 'highestmode', |
1453 | 0x16000060 => 'isolatedcontext', |
1471 | 0x16000060 => 'isolatedcontext', |
1454 | 0x15000065 => 'displaymessage', |
1472 | 0x15000065 => 'displaymessage', |
1455 | 0x15000066 => 'displaymessageoverride', |
1473 | 0x15000066 => 'displaymessageoverride', |
1456 | 0x16000068 => 'nobootuxtext', |
1474 | 0x16000068 => 'nobootuxtext', |
1457 | 0x16000069 => 'nobootuxprogress', |
1475 | 0x16000069 => 'nobootuxprogress', |
1458 | 0x1600006a => 'nobootuxfade', |
1476 | 0x1600006a => 'nobootuxfade', |
1459 | 0x1600006b => 'bootuxreservepooldebug', |
1477 | 0x1600006b => 'bootuxreservepooldebug', |
1460 | 0x1600006c => 'bootuxdisabled', |
1478 | 0x1600006c => 'bootuxdisabled', |
1461 | 0x1500006d => 'bootuxfadeframes', |
1479 | 0x1500006d => 'bootuxfadeframes', |
1462 | 0x1600006e => 'bootuxdumpstats', |
1480 | 0x1600006e => 'bootuxdumpstats', |
1463 | 0x1600006f => 'bootuxshowstats', |
1481 | 0x1600006f => 'bootuxshowstats', |
1464 | 0x16000071 => 'multibootsystem', |
1482 | 0x16000071 => 'multibootsystem', |
1465 | 0x16000072 => 'nokeyboard', |
1483 | 0x16000072 => 'nokeyboard', |
1466 | 0x15000073 => 'aliaswindowskey', |
1484 | 0x15000073 => 'aliaswindowskey', |
1467 | 0x16000074 => 'bootshutdowndisabled', |
1485 | 0x16000074 => 'bootshutdowndisabled', |
1468 | 0x15000075 => 'performancefrequency', |
1486 | 0x15000075 => 'performancefrequency', |
1469 | 0x15000076 => 'securebootrawpolicy', |
1487 | 0x15000076 => 'securebootrawpolicy', |
1470 | 0x17000077 => 'allowedinmemorysettings', |
1488 | 0x17000077 => 'allowedinmemorysettings', |
1471 | 0x15000079 => 'bootuxtransitiontime', |
1489 | 0x15000079 => 'bootuxtransitiontime', |
1472 | 0x1600007a => 'mobilegraphics', |
1490 | 0x1600007a => 'mobilegraphics', |
1473 | 0x1600007b => 'forcefipscrypto', |
1491 | 0x1600007b => 'forcefipscrypto', |
1474 | 0x1500007d => 'booterrorux', |
1492 | 0x1500007d => 'booterrorux', |
1475 | 0x1600007e => 'flightsigning', |
1493 | 0x1600007e => 'flightsigning', |
1476 | 0x1500007f => 'measuredbootlogformat', |
1494 | 0x1500007f => 'measuredbootlogformat', |
1477 | 0x15000080 => 'displayrotation', |
1495 | 0x15000080 => 'displayrotation', |
1478 | 0x15000081 => 'logcontrol', |
1496 | 0x15000081 => 'logcontrol', |
1479 | 0x16000082 => 'nofirmwaresync', |
1497 | 0x16000082 => 'nofirmwaresync', |
1480 | 0x11000084 => 'windowssyspart', |
1498 | 0x11000084 => 'windowssyspart', |
1481 | 0x16000087 => 'numlock', |
1499 | 0x16000087 => 'numlock', |
1482 | 0x22000001 => 'bpbstring', |
1500 | 0x26000202 => 'skipffumode', |
|
|
1501 | 0x26000203 => 'forceffumode', |
|
|
1502 | 0x25000510 => 'chargethreshold', |
|
|
1503 | 0x26000512 => 'offmodecharging', |
|
|
1504 | 0x25000aaa => 'bootflow', |
|
|
1505 | 0x45000001 => 'devicetype', |
|
|
1506 | 0x42000002 => 'applicationrelativepath', |
|
|
1507 | 0x42000003 => 'ramdiskdevicerelativepath', |
|
|
1508 | 0x46000004 => 'omitosloaderelements', |
|
|
1509 | 0x47000006 => 'elementstomigrate', |
|
|
1510 | 0x46000010 => 'recoveryos', |
|
|
1511 | }, |
|
|
1512 | bootapp => { |
|
|
1513 | 0x26000145 => 'enablebootdebugpolicy', |
|
|
1514 | 0x26000146 => 'enablebootorderclean', |
|
|
1515 | 0x26000147 => 'enabledeviceid', |
|
|
1516 | 0x26000148 => 'enableffuloader', |
|
|
1517 | 0x26000149 => 'enableiuloader', |
|
|
1518 | 0x2600014a => 'enablemassstorage', |
|
|
1519 | 0x2600014b => 'enablerpmbprovisioning', |
|
|
1520 | 0x2600014c => 'enablesecurebootpolicy', |
|
|
1521 | 0x2600014d => 'enablestartcharge', |
|
|
1522 | 0x2600014e => 'enableresettpm', |
|
|
1523 | }, |
|
|
1524 | bootmgr => { |
1483 | 0x24000001 => 'displayorder', |
1525 | 0x24000001 => 'displayorder', |
1484 | 0x21000001 => 'filedevice', |
|
|
1485 | 0x21000001 => 'osdevice', |
|
|
1486 | 0x25000001 => 'passcount', |
|
|
1487 | 0x26000001 => 'pxesoftreboot', |
|
|
1488 | 0x22000002 => 'applicationname', |
|
|
1489 | 0x24000002 => 'bootsequence', |
1526 | 0x24000002 => 'bootsequence', |
1490 | 0x22000002 => 'filepath', |
|
|
1491 | 0x22000002 => 'systemroot', |
|
|
1492 | 0x25000002 => 'testmix', |
|
|
1493 | 0x26000003 => 'cacheenable', |
|
|
1494 | 0x26000003 => 'customsettings', |
|
|
1495 | 0x23000003 => 'default', |
1527 | 0x23000003 => 'default', |
1496 | 0x25000003 => 'failurecount', |
|
|
1497 | 0x26000004 => 'failuresenabled', |
|
|
1498 | 0x26000004 => 'pae', |
|
|
1499 | 0x26000004 => 'stampdisks', |
|
|
1500 | 0x25000004 => 'testtofail', |
|
|
1501 | 0x25000004 => 'timeout', |
1528 | 0x25000004 => 'timeout', |
1502 | 0x21000005 => 'associatedosdevice', |
|
|
1503 | 0x26000005 => 'cacheenable', |
|
|
1504 | 0x26000005 => 'resume', |
1529 | 0x26000005 => 'resume', |
1505 | 0x25000005 => 'stridefailcount', |
|
|
1506 | 0x26000006 => 'debugoptionenabled', |
|
|
1507 | 0x25000006 => 'invcfailcount', |
|
|
1508 | 0x23000006 => 'resumeobject', |
1530 | 0x23000006 => 'resumeobject', |
1509 | 0x25000007 => 'bootux', |
|
|
1510 | 0x25000007 => 'matsfailcount', |
|
|
1511 | 0x24000007 => 'startupsequence', |
1531 | 0x24000007 => 'startupsequence', |
1512 | 0x25000008 => 'bootmenupolicy', |
|
|
1513 | 0x25000008 => 'randfailcount', |
|
|
1514 | 0x25000009 => 'chckrfailcount', |
|
|
1515 | 0x26000010 => 'detecthal', |
|
|
1516 | 0x24000010 => 'toolsdisplayorder', |
1532 | 0x24000010 => 'toolsdisplayorder', |
1517 | 0x22000011 => 'kernel', |
|
|
1518 | 0x22000012 => 'hal', |
|
|
1519 | 0x22000013 => 'dbgtransport', |
|
|
1520 | 0x26000020 => 'displaybootmenu', |
1533 | 0x26000020 => 'displaybootmenu', |
1521 | 0x25000020 => 'nx', |
|
|
1522 | 0x26000021 => 'noerrordisplay', |
1534 | 0x26000021 => 'noerrordisplay', |
1523 | 0x25000021 => 'pae', |
|
|
1524 | 0x21000022 => 'bcddevice', |
1535 | 0x21000022 => 'bcddevice', |
1525 | 0x26000022 => 'winpe', |
|
|
1526 | 0x22000023 => 'bcdfilepath', |
1536 | 0x22000023 => 'bcdfilepath', |
1527 | 0x26000024 => 'hormenabled', |
1537 | 0x26000024 => 'hormenabled', |
1528 | 0x26000024 => 'hormenabled', |
|
|
1529 | 0x26000024 => 'nocrashautoreboot', |
|
|
1530 | 0x26000025 => 'hiberboot', |
1538 | 0x26000025 => 'hiberboot', |
1531 | 0x26000025 => 'lastknowngood', |
|
|
1532 | 0x26000026 => 'oslnointegritychecks', |
|
|
1533 | 0x22000026 => 'passwordoverride', |
1539 | 0x22000026 => 'passwordoverride', |
1534 | 0x26000027 => 'osltestsigning', |
|
|
1535 | 0x22000027 => 'pinpassphraseoverride', |
1540 | 0x22000027 => 'pinpassphraseoverride', |
1536 | 0x26000028 => 'processcustomactionsfirst', |
1541 | 0x26000028 => 'processcustomactionsfirst', |
1537 | 0x27000030 => 'customactions', |
1542 | 0x27000030 => 'customactions', |
1538 | 0x26000030 => 'nolowmem', |
|
|
1539 | 0x26000031 => 'persistbootsequence', |
1543 | 0x26000031 => 'persistbootsequence', |
1540 | 0x25000031 => 'removememory', |
|
|
1541 | 0x25000032 => 'increaseuserva', |
|
|
1542 | 0x26000032 => 'skipstartupsequence', |
1544 | 0x26000032 => 'skipstartupsequence', |
1543 | 0x25000033 => 'perfmem', |
|
|
1544 | 0x22000040 => 'fverecoveryurl', |
1545 | 0x22000040 => 'fverecoveryurl', |
1545 | 0x26000040 => 'vga', |
|
|
1546 | 0x22000041 => 'fverecoverymessage', |
1546 | 0x22000041 => 'fverecoverymessage', |
|
|
1547 | }, |
|
|
1548 | device => { |
|
|
1549 | 0x35000001 => 'ramdiskimageoffset', |
|
|
1550 | 0x35000002 => 'ramdisktftpclientport', |
|
|
1551 | 0x31000003 => 'ramdisksdidevice', |
|
|
1552 | 0x32000004 => 'ramdisksdipath', |
|
|
1553 | 0x35000005 => 'ramdiskimagelength', |
|
|
1554 | 0x36000006 => 'exportascd', |
|
|
1555 | 0x35000007 => 'ramdisktftpblocksize', |
|
|
1556 | 0x35000008 => 'ramdisktftpwindowsize', |
|
|
1557 | 0x36000009 => 'ramdiskmcenabled', |
|
|
1558 | 0x3600000a => 'ramdiskmctftpfallback', |
|
|
1559 | 0x3600000b => 'ramdisktftpvarwindow', |
|
|
1560 | }, |
|
|
1561 | memdiag => { |
|
|
1562 | 0x25000001 => 'passcount', |
|
|
1563 | 0x25000002 => 'testmix', |
|
|
1564 | 0x25000003 => 'failurecount', |
|
|
1565 | 0x26000003 => 'cacheenable', |
|
|
1566 | 0x25000004 => 'testtofail', |
|
|
1567 | 0x26000004 => 'failuresenabled', |
|
|
1568 | 0x25000005 => 'stridefailcount', |
|
|
1569 | 0x26000005 => 'cacheenable', |
|
|
1570 | 0x25000006 => 'invcfailcount', |
|
|
1571 | 0x25000007 => 'matsfailcount', |
|
|
1572 | 0x25000008 => 'randfailcount', |
|
|
1573 | 0x25000009 => 'chckrfailcount', |
|
|
1574 | }, |
|
|
1575 | ntldr => { |
|
|
1576 | 0x22000001 => 'bpbstring', |
|
|
1577 | }, |
|
|
1578 | osloader => { |
|
|
1579 | 0x21000001 => 'osdevice', |
|
|
1580 | 0x22000002 => 'systemroot', |
|
|
1581 | 0x23000003 => 'resumeobject', |
|
|
1582 | 0x26000004 => 'stampdisks', |
|
|
1583 | 0x26000010 => 'detecthal', |
|
|
1584 | 0x22000011 => 'kernel', |
|
|
1585 | 0x22000012 => 'hal', |
|
|
1586 | 0x22000013 => 'dbgtransport', |
|
|
1587 | 0x25000020 => 'nx', |
|
|
1588 | 0x25000021 => 'pae', |
|
|
1589 | 0x26000022 => 'winpe', |
|
|
1590 | 0x26000024 => 'nocrashautoreboot', |
|
|
1591 | 0x26000025 => 'lastknowngood', |
|
|
1592 | 0x26000026 => 'oslnointegritychecks', |
|
|
1593 | 0x26000027 => 'osltestsigning', |
|
|
1594 | 0x26000030 => 'nolowmem', |
|
|
1595 | 0x25000031 => 'removememory', |
|
|
1596 | 0x25000032 => 'increaseuserva', |
|
|
1597 | 0x25000033 => 'perfmem', |
|
|
1598 | 0x26000040 => 'vga', |
1547 | 0x26000041 => 'quietboot', |
1599 | 0x26000041 => 'quietboot', |
1548 | 0x26000042 => 'novesa', |
1600 | 0x26000042 => 'novesa', |
1549 | 0x26000043 => 'novga', |
1601 | 0x26000043 => 'novga', |
1550 | 0x25000050 => 'clustermodeaddressing', |
1602 | 0x25000050 => 'clustermodeaddressing', |
1551 | 0x26000051 => 'usephysicaldestination', |
1603 | 0x26000051 => 'usephysicaldestination', |
1552 | 0x25000052 => 'restrictapiccluster', |
1604 | 0x25000052 => 'restrictapiccluster', |
1553 | 0x22000053 => 'evstore', |
1605 | 0x22000053 => 'evstore', |
1554 | 0x26000054 => 'uselegacyapicmode', |
1606 | 0x26000054 => 'uselegacyapicmode', |
1555 | 0x26000060 => 'onecpu', |
1607 | 0x26000060 => 'onecpu', |
1556 | 0x25000061 => 'numproc', |
1608 | 0x25000061 => 'numproc', |
1557 | 0x26000062 => 'maxproc', |
1609 | 0x26000062 => 'maxproc', |
1558 | 0x25000063 => 'configflags', |
1610 | 0x25000063 => 'configflags', |
1559 | 0x26000064 => 'maxgroup', |
1611 | 0x26000064 => 'maxgroup', |
1560 | 0x26000065 => 'groupaware', |
1612 | 0x26000065 => 'groupaware', |
1561 | 0x25000066 => 'groupsize', |
1613 | 0x25000066 => 'groupsize', |
1562 | 0x26000070 => 'usefirmwarepcisettings', |
1614 | 0x26000070 => 'usefirmwarepcisettings', |
1563 | 0x25000071 => 'msi', |
1615 | 0x25000071 => 'msi', |
1564 | 0x25000072 => 'pciexpress', |
1616 | 0x25000072 => 'pciexpress', |
1565 | 0x25000080 => 'safeboot', |
1617 | 0x25000080 => 'safeboot', |
1566 | 0x26000081 => 'safebootalternateshell', |
1618 | 0x26000081 => 'safebootalternateshell', |
1567 | 0x26000090 => 'bootlog', |
1619 | 0x26000090 => 'bootlog', |
1568 | 0x26000091 => 'sos', |
1620 | 0x26000091 => 'sos', |
1569 | 0x260000a0 => 'debug', |
1621 | 0x260000a0 => 'debug', |
1570 | 0x260000a1 => 'halbreakpoint', |
1622 | 0x260000a1 => 'halbreakpoint', |
1571 | 0x260000a2 => 'useplatformclock', |
1623 | 0x260000a2 => 'useplatformclock', |
1572 | 0x260000a3 => 'forcelegacyplatform', |
1624 | 0x260000a3 => 'forcelegacyplatform', |
1573 | 0x260000a4 => 'useplatformtick', |
1625 | 0x260000a4 => 'useplatformtick', |
1574 | 0x260000a5 => 'disabledynamictick', |
1626 | 0x260000a5 => 'disabledynamictick', |
1575 | 0x250000a6 => 'tscsyncpolicy', |
1627 | 0x250000a6 => 'tscsyncpolicy', |
1576 | 0x260000b0 => 'ems', |
1628 | 0x260000b0 => 'ems', |
1577 | 0x250000c0 => 'forcefailure', |
1629 | 0x250000c0 => 'forcefailure', |
1578 | 0x250000c1 => 'driverloadfailurepolicy', |
1630 | 0x250000c1 => 'driverloadfailurepolicy', |
1579 | 0x250000c2 => 'bootmenupolicy', |
1631 | 0x250000c2 => 'bootmenupolicy', |
1580 | 0x260000c3 => 'onetimeadvancedoptions', |
1632 | 0x260000c3 => 'onetimeadvancedoptions', |
1581 | 0x260000c4 => 'onetimeoptionsedit', |
1633 | 0x260000c4 => 'onetimeoptionsedit', |
1582 | 0x250000e0 => 'bootstatuspolicy', |
1634 | 0x250000e0 => 'bootstatuspolicy', |
1583 | 0x260000e1 => 'disableelamdrivers', |
1635 | 0x260000e1 => 'disableelamdrivers', |
1584 | 0x250000f0 => 'hypervisorlaunchtype', |
1636 | 0x250000f0 => 'hypervisorlaunchtype', |
1585 | 0x220000f1 => 'hypervisorpath', |
1637 | 0x220000f1 => 'hypervisorpath', |
1586 | 0x260000f2 => 'hypervisordebug', |
1638 | 0x260000f2 => 'hypervisordebug', |
1587 | 0x250000f3 => 'hypervisordebugtype', |
1639 | 0x250000f3 => 'hypervisordebugtype', |
1588 | 0x250000f4 => 'hypervisordebugport', |
1640 | 0x250000f4 => 'hypervisordebugport', |
1589 | 0x250000f5 => 'hypervisorbaudrate', |
1641 | 0x250000f5 => 'hypervisorbaudrate', |
1590 | 0x250000f6 => 'hypervisorchannel', |
1642 | 0x250000f6 => 'hypervisorchannel', |
1591 | 0x250000f7 => 'bootux', |
1643 | 0x250000f7 => 'bootux', |
1592 | 0x260000f8 => 'hypervisordisableslat', |
1644 | 0x260000f8 => 'hypervisordisableslat', |
1593 | 0x220000f9 => 'hypervisorbusparams', |
1645 | 0x220000f9 => 'hypervisorbusparams', |
1594 | 0x250000fa => 'hypervisornumproc', |
1646 | 0x250000fa => 'hypervisornumproc', |
1595 | 0x250000fb => 'hypervisorrootprocpernode', |
1647 | 0x250000fb => 'hypervisorrootprocpernode', |
1596 | 0x260000fc => 'hypervisoruselargevtlb', |
1648 | 0x260000fc => 'hypervisoruselargevtlb', |
1597 | 0x250000fd => 'hypervisorhostip', |
1649 | 0x250000fd => 'hypervisorhostip', |
1598 | 0x250000fe => 'hypervisorhostport', |
1650 | 0x250000fe => 'hypervisorhostport', |
1599 | 0x250000ff => 'hypervisordebugpages', |
1651 | 0x250000ff => 'hypervisordebugpages', |
1600 | 0x25000100 => 'tpmbootentropy', |
1652 | 0x25000100 => 'tpmbootentropy', |
1601 | 0x22000110 => 'hypervisorusekey', |
1653 | 0x22000110 => 'hypervisorusekey', |
1602 | 0x22000112 => 'hypervisorproductskutype', |
1654 | 0x22000112 => 'hypervisorproductskutype', |
1603 | 0x25000113 => 'hypervisorrootproc', |
1655 | 0x25000113 => 'hypervisorrootproc', |
1604 | 0x26000114 => 'hypervisordhcp', |
1656 | 0x26000114 => 'hypervisordhcp', |
1605 | 0x25000115 => 'hypervisoriommupolicy', |
1657 | 0x25000115 => 'hypervisoriommupolicy', |
1606 | 0x26000116 => 'hypervisorusevapic', |
1658 | 0x26000116 => 'hypervisorusevapic', |
1607 | 0x22000117 => 'hypervisorloadoptions', |
1659 | 0x22000117 => 'hypervisorloadoptions', |
1608 | 0x25000118 => 'hypervisormsrfilterpolicy', |
1660 | 0x25000118 => 'hypervisormsrfilterpolicy', |
1609 | 0x25000119 => 'hypervisormmionxpolicy', |
1661 | 0x25000119 => 'hypervisormmionxpolicy', |
1610 | 0x2500011a => 'hypervisorschedulertype', |
1662 | 0x2500011a => 'hypervisorschedulertype', |
1611 | 0x25000120 => 'xsavepolicy', |
1663 | 0x25000120 => 'xsavepolicy', |
1612 | 0x25000121 => 'xsaveaddfeature0', |
1664 | 0x25000121 => 'xsaveaddfeature0', |
1613 | 0x25000122 => 'xsaveaddfeature1', |
1665 | 0x25000122 => 'xsaveaddfeature1', |
1614 | 0x25000123 => 'xsaveaddfeature2', |
1666 | 0x25000123 => 'xsaveaddfeature2', |
1615 | 0x25000124 => 'xsaveaddfeature3', |
1667 | 0x25000124 => 'xsaveaddfeature3', |
1616 | 0x25000125 => 'xsaveaddfeature4', |
1668 | 0x25000125 => 'xsaveaddfeature4', |
1617 | 0x25000126 => 'xsaveaddfeature5', |
1669 | 0x25000126 => 'xsaveaddfeature5', |
1618 | 0x25000127 => 'xsaveaddfeature6', |
1670 | 0x25000127 => 'xsaveaddfeature6', |
1619 | 0x25000128 => 'xsaveaddfeature7', |
1671 | 0x25000128 => 'xsaveaddfeature7', |
1620 | 0x25000129 => 'xsaveremovefeature', |
1672 | 0x25000129 => 'xsaveremovefeature', |
1621 | 0x2500012a => 'xsaveprocessorsmask', |
1673 | 0x2500012a => 'xsaveprocessorsmask', |
1622 | 0x2500012b => 'xsavedisable', |
1674 | 0x2500012b => 'xsavedisable', |
1623 | 0x2500012c => 'kerneldebugtype', |
1675 | 0x2500012c => 'kerneldebugtype', |
1624 | 0x2200012d => 'kernelbusparams', |
1676 | 0x2200012d => 'kernelbusparams', |
1625 | 0x2500012e => 'kerneldebugaddress', |
1677 | 0x2500012e => 'kerneldebugaddress', |
1626 | 0x2500012f => 'kerneldebugport', |
1678 | 0x2500012f => 'kerneldebugport', |
1627 | 0x25000130 => 'claimedtpmcounter', |
1679 | 0x25000130 => 'claimedtpmcounter', |
1628 | 0x25000131 => 'kernelchannel', |
1680 | 0x25000131 => 'kernelchannel', |
1629 | 0x22000132 => 'kerneltargetname', |
1681 | 0x22000132 => 'kerneltargetname', |
1630 | 0x25000133 => 'kernelhostip', |
1682 | 0x25000133 => 'kernelhostip', |
1631 | 0x25000134 => 'kernelport', |
1683 | 0x25000134 => 'kernelport', |
1632 | 0x26000135 => 'kerneldhcp', |
1684 | 0x26000135 => 'kerneldhcp', |
1633 | 0x22000136 => 'kernelkey', |
1685 | 0x22000136 => 'kernelkey', |
1634 | 0x22000137 => 'imchivename', |
1686 | 0x22000137 => 'imchivename', |
1635 | 0x21000138 => 'imcdevice', |
1687 | 0x21000138 => 'imcdevice', |
1636 | 0x25000139 => 'kernelbaudrate', |
1688 | 0x25000139 => 'kernelbaudrate', |
1637 | 0x22000140 => 'mfgmode', |
1689 | 0x22000140 => 'mfgmode', |
1638 | 0x26000141 => 'event', |
1690 | 0x26000141 => 'event', |
1639 | 0x25000142 => 'vsmlaunchtype', |
1691 | 0x25000142 => 'vsmlaunchtype', |
1640 | 0x25000144 => 'hypervisorenforcedcodeintegrity', |
1692 | 0x25000144 => 'hypervisorenforcedcodeintegrity', |
1641 | 0x26000145 => 'enablebootdebugpolicy', |
|
|
1642 | 0x26000146 => 'enablebootorderclean', |
|
|
1643 | 0x26000147 => 'enabledeviceid', |
|
|
1644 | 0x26000148 => 'enableffuloader', |
|
|
1645 | 0x26000149 => 'enableiuloader', |
|
|
1646 | 0x2600014a => 'enablemassstorage', |
|
|
1647 | 0x2600014b => 'enablerpmbprovisioning', |
|
|
1648 | 0x2600014c => 'enablesecurebootpolicy', |
|
|
1649 | 0x2600014d => 'enablestartcharge', |
|
|
1650 | 0x2600014e => 'enableresettpm', |
|
|
1651 | 0x21000150 => 'systemdatadevice', |
1693 | 0x21000150 => 'systemdatadevice', |
1652 | 0x21000151 => 'osarcdevice', |
1694 | 0x21000151 => 'osarcdevice', |
1653 | 0x21000153 => 'osdatadevice', |
1695 | 0x21000153 => 'osdatadevice', |
1654 | 0x21000154 => 'bspdevice', |
1696 | 0x21000154 => 'bspdevice', |
1655 | 0x21000155 => 'bspfilepath', |
1697 | 0x21000155 => 'bspfilepath', |
1656 | 0x26000202 => 'skipffumode', |
1698 | }, |
1657 | 0x26000203 => 'forceffumode', |
1699 | resume => { |
1658 | 0x25000510 => 'chargethreshold', |
1700 | 0x21000001 => 'filedevice', |
1659 | 0x26000512 => 'offmodecharging', |
1701 | 0x22000002 => 'filepath', |
1660 | 0x25000aaa => 'bootflow', |
1702 | 0x26000003 => 'customsettings', |
1661 | 0x35000001 => 'ramdiskimageoffset', |
1703 | 0x26000004 => 'pae', |
1662 | 0x35000002 => 'ramdisktftpclientport', |
1704 | 0x21000005 => 'associatedosdevice', |
1663 | 0x31000003 => 'ramdisksdidevice', |
1705 | 0x26000006 => 'debugoptionenabled', |
1664 | 0x32000004 => 'ramdisksdipath', |
1706 | 0x25000007 => 'bootux', |
1665 | 0x35000005 => 'ramdiskimagelength', |
1707 | 0x25000008 => 'bootmenupolicy', |
1666 | 0x36000006 => 'exportascd', |
1708 | 0x26000024 => 'hormenabled', |
1667 | 0x35000007 => 'ramdisktftpblocksize', |
1709 | }, |
1668 | 0x35000008 => 'ramdisktftpwindowsize', |
1710 | startup => { |
1669 | 0x36000009 => 'ramdiskmcenabled', |
1711 | 0x26000001 => 'pxesoftreboot', |
1670 | 0x3600000a => 'ramdiskmctftpfallback', |
1712 | 0x22000002 => 'applicationname', |
1671 | 0x3600000b => 'ramdisktftpvarwindow', |
1713 | }, |
1672 | 0x45000001 => 'devicetype', |
|
|
1673 | 0x42000002 => 'applicationrelativepath', |
|
|
1674 | 0x42000003 => 'ramdiskdevicerelativepath', |
|
|
1675 | 0x46000004 => 'omitosloaderelements', |
|
|
1676 | 0x47000006 => 'elementstomigrate', |
|
|
1677 | 0x46000010 => 'recoveryos', |
|
|
1678 | ); |
1714 | ); |
1679 | |
1715 | |
1680 | our %rbcde = reverse %bcde; |
1716 | # mask, value => class |
|
|
1717 | our @bcde_typeclass = ( |
|
|
1718 | [0x00000000, 0x00000000, 'any'], |
|
|
1719 | [0xf00fffff, 0x1000000a, 'bootapp'], |
|
|
1720 | [0xf0ffffff, 0x2020000a, 'bootapp'], |
|
|
1721 | [0xf00fffff, 0x10000001, 'bootmgr'], |
|
|
1722 | [0xf00fffff, 0x10000002, 'bootmgr'], |
|
|
1723 | [0xf0ffffff, 0x20200001, 'bootmgr'], |
|
|
1724 | [0xf0ffffff, 0x20200002, 'bootmgr'], |
|
|
1725 | [0xf0f00000, 0x20300000, 'device'], |
|
|
1726 | [0xf0000000, 0x30000000, 'device'], |
|
|
1727 | [0xf00fffff, 0x10000005, 'memdiag'], |
|
|
1728 | [0xf0ffffff, 0x20200005, 'memdiag'], |
|
|
1729 | [0xf00fffff, 0x10000006, 'ntldr'], |
|
|
1730 | [0xf00fffff, 0x10000007, 'ntldr'], |
|
|
1731 | [0xf0ffffff, 0x20200006, 'ntldr'], |
|
|
1732 | [0xf0ffffff, 0x20200007, 'ntldr'], |
|
|
1733 | [0xf00fffff, 0x10000003, 'osloader'], |
|
|
1734 | [0xf0ffffff, 0x20200003, 'osloader'], |
|
|
1735 | [0xf00fffff, 0x10000004, 'resume'], |
|
|
1736 | [0xf0ffffff, 0x20200004, 'resume'], |
|
|
1737 | [0xf00fffff, 0x10000009, 'startup'], |
|
|
1738 | [0xf0ffffff, 0x20200009, 'startup'], |
|
|
1739 | ); |
1681 | |
1740 | |
|
|
1741 | our %rbcde_byclass; |
|
|
1742 | |
|
|
1743 | while (my ($k, $v) = each %bcde_byclass) { |
|
|
1744 | $rbcde_byclass{$k} = { reverse %$v }; |
|
|
1745 | } |
|
|
1746 | |
|
|
1747 | # decodes (numerical elem, type) to name |
1682 | sub dec_bcde_id($) { |
1748 | sub dec_bcde_id($$) { |
|
|
1749 | for my $class (@bcde_typeclass) { |
|
|
1750 | if (($_[1] & $class->[0]) == $class->[1]) { |
|
|
1751 | if (my $id = $bcde_byclass{$class->[2]}{$_[0]}) { |
|
|
1752 | return $id; |
|
|
1753 | } |
|
|
1754 | } |
|
|
1755 | } |
|
|
1756 | |
1683 | $bcde{$_[0]} // sprintf "custom:%08x", $_[0] |
1757 | sprintf "custom:%08x", $_[0] |
1684 | } |
1758 | } |
1685 | |
1759 | |
|
|
1760 | # encodes (elem as name, type) |
1686 | sub enc_bcde_id($) { |
1761 | sub enc_bcde_id($$) { |
1687 | $_[0] =~ /^custom:([0-9a-fA-F]{8}$)/ |
1762 | $_[0] =~ /^custom:(?:0x)?([0-9a-fA-F]{8}$)/ |
1688 | ? hex $1 |
1763 | and return hex $1; |
1689 | : $rbcde{$_[0]} |
1764 | |
|
|
1765 | for my $class (@bcde_typeclass) { |
|
|
1766 | if (($_[1] & $class->[0]) == $class->[1]) { |
|
|
1767 | if (my $value = $rbcde_byclass{$class->[2]}{$_[0]}) { |
|
|
1768 | return $value; |
|
|
1769 | } |
|
|
1770 | } |
|
|
1771 | } |
|
|
1772 | |
|
|
1773 | undef |
1690 | } |
1774 | } |
1691 | |
1775 | |
1692 | # decode/encode bcd device element - the horror, no documentaion |
1776 | # decode/encode bcd device element - the horror, no documentaion |
1693 | # whatsoever, supercomplex, superinconsistent. |
1777 | # whatsoever, supercomplex, superinconsistent. |
1694 | |
1778 | |
… | |
… | |
1698 | |
1782 | |
1699 | our $NULL_DEVICE = "\x00" x 16; |
1783 | our $NULL_DEVICE = "\x00" x 16; |
1700 | |
1784 | |
1701 | # biggest bitch to decode, ever |
1785 | # biggest bitch to decode, ever |
1702 | # this decoded a device portion after the GUID |
1786 | # this decoded a device portion after the GUID |
1703 | sub dec_device_($); |
1787 | sub dec_device_($$); |
1704 | sub dec_device_($) { |
1788 | sub dec_device_($$) { |
1705 | my ($device) = @_; |
1789 | my ($device, $type) = @_; |
1706 | |
1790 | |
1707 | my $res; |
1791 | my $res; |
1708 | |
1792 | |
1709 | my ($type, $flags, $length, $pad) = unpack "VVVV", substr $device, 0, 4 * 4, ""; |
1793 | my ($type, $flags, $length, $pad) = unpack "VVVV", substr $device, 0, 4 * 4, ""; |
1710 | |
1794 | |
… | |
… | |
1755 | |
1839 | |
1756 | my $partid = $parttype eq "gpt" ? dec_guid $partdata |
1840 | my $partid = $parttype eq "gpt" ? dec_guid $partdata |
1757 | : $type eq "partition" ? unpack "Q<", $partdata # byte offset to partition start |
1841 | : $type eq "partition" ? unpack "Q<", $partdata # byte offset to partition start |
1758 | : unpack "L<", $partdata; # partition number, one-based |
1842 | : unpack "L<", $partdata; # partition number, one-based |
1759 | |
1843 | |
1760 | (my $parent, $device) = dec_device_ $device; |
1844 | (my $parent, $device) = dec_device_ $device, $type; |
1761 | |
1845 | |
1762 | $res .= "="; |
1846 | $res .= "="; |
1763 | $res .= "<$parent>"; |
1847 | $res .= "<$parent>"; |
1764 | $res .= ",$blocktype,$parttype,$diskid,$partid"; |
1848 | $res .= ",$blocktype,$parttype,$diskid,$partid"; |
1765 | |
1849 | |
… | |
… | |
1785 | or die "unsupported file descriptor version '$fver'\n"; |
1869 | or die "unsupported file descriptor version '$fver'\n"; |
1786 | |
1870 | |
1787 | $ftype == 5 |
1871 | $ftype == 5 |
1788 | or die "unsupported file descriptor path type '$type'\n"; |
1872 | or die "unsupported file descriptor path type '$type'\n"; |
1789 | |
1873 | |
1790 | (my $parent, $path) = dec_device_ $path; |
1874 | (my $parent, $path) = dec_device_ $path, $type; |
1791 | |
1875 | |
1792 | $path = $dec_path->($path, "file device without path"); |
1876 | $path = $dec_path->($path, "file device without path"); |
1793 | |
1877 | |
1794 | ($parent, $path) |
1878 | ($parent, $path) |
1795 | }; |
1879 | }; |
… | |
… | |
1801 | |
1885 | |
1802 | } elsif ($blocktype eq "vhd") { |
1886 | } elsif ($blocktype eq "vhd") { |
1803 | $device =~ s/^\x00{20}//s |
1887 | $device =~ s/^\x00{20}//s |
1804 | or die "virtualdisk has non-zero fields I don't understand\n"; |
1888 | or die "virtualdisk has non-zero fields I don't understand\n"; |
1805 | |
1889 | |
1806 | (my $parent, $device) = dec_device_ $device; |
1890 | (my $parent, $device) = dec_device_ $device, $type; |
1807 | |
1891 | |
1808 | $res .= "=vhd,<$parent>"; |
1892 | $res .= "=vhd,<$parent>"; |
1809 | |
1893 | |
1810 | } elsif ($blocktype eq "ramdisk") { |
1894 | } elsif ($blocktype eq "ramdisk") { |
1811 | my ($base, $size, $offset) = unpack "Q< Q< L<", substr $device, 0, 8 + 8 + 4, ""; |
1895 | my ($base, $size, $offset) = unpack "Q< Q< L<", substr $device, 0, 8 + 8 + 4, ""; |
… | |
… | |
1824 | my ($mode, $elem, $parent) = unpack "VVV", substr $device, 0, 4 * 3, ""; |
1908 | my ($mode, $elem, $parent) = unpack "VVV", substr $device, 0, 4 * 3, ""; |
1825 | |
1909 | |
1826 | if ($parent) { |
1910 | if ($parent) { |
1827 | # not sure why this is an offset - it must come after the path |
1911 | # not sure why this is an offset - it must come after the path |
1828 | $parent = substr $device, $parent - 4 * 3 - 4 * 4, 1e9, ""; |
1912 | $parent = substr $device, $parent - 4 * 3 - 4 * 4, 1e9, ""; |
1829 | ($parent, my $tail) = dec_device_ $parent; |
1913 | ($parent, my $tail) = dec_device_ $parent, $type; |
1830 | 0 == length $tail |
1914 | 0 == length $tail |
1831 | or die "trailing data after locate device parent\n"; |
1915 | or die "trailing data after locate device parent\n"; |
1832 | } else { |
1916 | } else { |
1833 | $parent = "null"; |
1917 | $parent = "null"; |
1834 | } |
1918 | } |
… | |
… | |
1840 | |
1924 | |
1841 | if ($mode == 0) { # "Element" |
1925 | if ($mode == 0) { # "Element" |
1842 | !length $path |
1926 | !length $path |
1843 | or die "device locate mode 0 having non-empty path ($mode, $elem, $path)\n"; |
1927 | or die "device locate mode 0 having non-empty path ($mode, $elem, $path)\n"; |
1844 | |
1928 | |
1845 | $elem = dec_bcde_id $elem; |
1929 | $elem = dec_bcde_id $elem, $type; |
1846 | $res .= "element,$elem"; |
1930 | $res .= "element,$elem"; |
1847 | |
1931 | |
1848 | } elsif ($mode == 1) { # "String" |
1932 | } elsif ($mode == 1) { # "String" |
1849 | !$elem |
1933 | !$elem |
1850 | or die "device locate mode 1 having non-zero element\n"; |
1934 | or die "device locate mode 1 having non-zero element\n"; |
… | |
… | |
1875 | |
1959 | |
1876 | ($res, $tail) |
1960 | ($res, $tail) |
1877 | } |
1961 | } |
1878 | |
1962 | |
1879 | # decode a full binary BCD device descriptor |
1963 | # decode a full binary BCD device descriptor |
1880 | sub dec_device($) { |
1964 | sub dec_device($$) { |
1881 | my ($device) = @_; |
1965 | my ($device, $type) = @_; |
1882 | |
1966 | |
1883 | $device = pack "H*", $device; |
1967 | $device = pack "H*", $device; |
1884 | |
1968 | |
1885 | my $guid = dec_guid substr $device, 0, 16, ""; |
1969 | my $guid = dec_guid substr $device, 0, 16, ""; |
1886 | $guid = $guid eq "00000000-0000-0000-0000-000000000000" |
1970 | $guid = $guid eq "00000000-0000-0000-0000-000000000000" |
1887 | ? "" : "{$guid}"; |
1971 | ? "" : "{$guid}"; |
1888 | |
1972 | |
1889 | eval { |
1973 | eval { |
1890 | my ($dev, $tail) = dec_device_ $device; |
1974 | my ($dev, $tail) = dec_device_ $device, $type; |
1891 | |
1975 | |
1892 | $tail eq "" |
1976 | $tail eq "" |
1893 | or die "unsupported trailing data after device descriptor\n"; |
1977 | or die "unsupported trailing data after device descriptor\n"; |
1894 | |
1978 | |
1895 | "$guid$dev" |
1979 | "$guid$dev" |
… | |
… | |
1907 | |
1991 | |
1908 | undef |
1992 | undef |
1909 | } |
1993 | } |
1910 | |
1994 | |
1911 | # encode the device portion after the GUID |
1995 | # encode the device portion after the GUID |
1912 | sub enc_device_; |
1996 | sub enc_device_($$); |
1913 | sub enc_device_ { |
1997 | sub enc_device_($$) { |
1914 | my ($device) = @_; |
1998 | my ($device, $type) = @_; |
1915 | |
1999 | |
1916 | my $enc_path = sub { |
2000 | my $enc_path = sub { |
1917 | my $path = shift; |
2001 | my $path = shift; |
1918 | $path =~ s/\//\\/g; |
2002 | $path =~ s/\//\\/g; |
1919 | (Encode::encode "UTF-16LE", $path) . "\x00\x00" |
2003 | (Encode::encode "UTF-16LE", $path) . "\x00\x00" |
… | |
… | |
1937 | |
2021 | |
1938 | my $parse_parent = sub { |
2022 | my $parse_parent = sub { |
1939 | my $parent; |
2023 | my $parent; |
1940 | |
2024 | |
1941 | if (s/^<//) { |
2025 | if (s/^<//) { |
1942 | ($parent, $_) = enc_device_ $_; |
2026 | ($parent, $_) = enc_device_ $_, $type; |
1943 | s/^>// |
2027 | s/^>// |
1944 | or die "$device: syntax error: parent device not followed by '>'\n"; |
2028 | or die "$device: syntax error: parent device not followed by '>'\n"; |
1945 | } else { |
2029 | } else { |
1946 | $parent = $NULL_DEVICE; |
2030 | $parent = $NULL_DEVICE; |
1947 | } |
2031 | } |
… | |
… | |
2035 | |
2119 | |
2036 | s/^,// |
2120 | s/^,// |
2037 | or die "$_: missing comma after locate parent device\n"; |
2121 | or die "$_: missing comma after locate parent device\n"; |
2038 | |
2122 | |
2039 | if (s/^element,//) { |
2123 | if (s/^element,//) { |
2040 | s/^([0-9a-z]+)//i |
2124 | s/^([0-9a-z:]+)//i |
2041 | or die "$_ locate element must be either name or 8-digit hex id\n"; |
2125 | or die "$_ locate element must be either name or 8-digit hex id\n"; |
2042 | $elem = enc_bcde_id $1; |
2126 | $elem = enc_bcde_id $1, $type; |
2043 | $mode = 0; |
2127 | $mode = 0; |
2044 | $path = $enc_path->(""); |
2128 | $path = $enc_path->(""); |
2045 | |
2129 | |
2046 | } elsif (s/^path,//) { |
2130 | } elsif (s/^path,//) { |
2047 | $mode = 1; |
2131 | $mode = 1; |
… | |
… | |
2126 | ); |
2210 | ); |
2127 | } |
2211 | } |
2128 | } |
2212 | } |
2129 | |
2213 | |
2130 | # encode a full binary BCD device descriptor |
2214 | # encode a full binary BCD device descriptor |
2131 | sub enc_device { |
2215 | sub enc_device($$) { |
2132 | my ($device) = @_; |
2216 | my ($device, $type) = @_; |
2133 | |
2217 | |
2134 | my $guid = "\x00" x 16; |
2218 | my $guid = "\x00" x 16; |
2135 | |
2219 | |
2136 | if ($device =~ s/^\{([A-Za-z0-9\-]+)\}//) { |
2220 | if ($device =~ s/^\{([A-Za-z0-9\-]+)\}//) { |
2137 | $guid = enc_guid $1 |
2221 | $guid = enc_guid $1 |
2138 | or die "$device: does not start with valid guid\n"; |
2222 | or die "$device: does not start with valid guid\n"; |
2139 | } |
2223 | } |
2140 | |
2224 | |
2141 | my ($descriptor, $tail) = enc_device_ $device; |
2225 | my ($descriptor, $tail) = enc_device_ $device, $type; |
2142 | |
2226 | |
2143 | length $tail |
2227 | length $tail |
2144 | and die "$device: garbage after device descriptor\n"; |
2228 | and die "$device: garbage after device descriptor\n"; |
2145 | |
2229 | |
2146 | unpack "H*", $guid . $descriptor |
2230 | unpack "H*", $guid . $descriptor |
… | |
… | |
2161 | $k = $bcd_objects{$k} // $k; |
2245 | $k = $bcd_objects{$k} // $k; |
2162 | |
2246 | |
2163 | my $type = $v->{Description}[0]{Type}[1]; |
2247 | my $type = $v->{Description}[0]{Type}[1]; |
2164 | |
2248 | |
2165 | if ($type != $bcd_object_types{$k}) { |
2249 | if ($type != $bcd_object_types{$k}) { |
2166 | $type = $bcd_types{$type} // sprintf "0x%08x", $type; |
2250 | $kv{type} = $bcd_types{$type} // sprintf "0x%08x", $type; |
2167 | $kv{type} = $type; |
|
|
2168 | } |
2251 | } |
2169 | |
2252 | |
2170 | my $elems = $v->{Elements}[1]; |
2253 | my $elems = $v->{Elements}[1]; |
2171 | |
2254 | |
2172 | while (my ($k, $v) = each %$elems) { |
2255 | while (my ($k, $v) = each %$elems) { |
2173 | my $k = hex $k; |
2256 | my $k = hex $k; |
2174 | |
2257 | |
2175 | my $v = $bcde_dec{$k & BCDE_FORMAT}->($v->[0]{Element}[1]); |
2258 | my $v = $bcde_dec{$k & BCDE_FORMAT}->($v->[0]{Element}[1], $type); |
2176 | my $k = dec_bcde_id $k; |
2259 | my $k = dec_bcde_id $k, $type; |
2177 | |
2260 | |
2178 | $kv{$k} = $v; |
2261 | $kv{$k} = $v; |
2179 | } |
2262 | } |
2180 | |
2263 | |
2181 | $bcd{$k} = \%kv; |
2264 | $bcd{$k} = \%kv; |
… | |
… | |
2222 | my %elem; |
2305 | my %elem; |
2223 | |
2306 | |
2224 | while (my ($k, $v) = each %$v) { |
2307 | while (my ($k, $v) = each %$v) { |
2225 | next if $k eq "type"; |
2308 | next if $k eq "type"; |
2226 | |
2309 | |
2227 | $k = (enc_bcde_id $k) // die "$k: invalid bcde element name or id\n"; |
2310 | $k = (enc_bcde_id $k, $type) // die "$k: invalid bcde element name or id\n"; |
2228 | $elem{sprintf "%08x", $k} = [{ |
2311 | $elem{sprintf "%08x", $k} = [{ |
2229 | Element => [ ($bcde_enc{$k & BCDE_FORMAT} // die "$k: unable to encode unknown bcd element type}")->($v)] |
2312 | Element => [ ($bcde_enc{$k & BCDE_FORMAT} // die "$k: unable to encode unknown bcd element type}")->($v)] |
2230 | }]; |
2313 | }]; |
2231 | } |
2314 | } |
2232 | |
2315 | |
… | |
… | |
2355 | |
2438 | |
2356 | print "\n"; |
2439 | print "\n"; |
2357 | |
2440 | |
2358 | printf "%-39s %-23s %s\n", "Object GUID", "Alias", "(Hex) Default Type"; |
2441 | printf "%-39s %-23s %s\n", "Object GUID", "Alias", "(Hex) Default Type"; |
2359 | for my $name (sort keys %rbcd_objects) { |
2442 | for my $name (sort keys %rbcd_objects) { |
2360 | my $guid = $rbcd_objects{$name}; |
2443 | my $guid = $rbcd_objects{$name}; |
2361 | my $type = $bcd_object_types{$name}; |
2444 | my $type = $bcd_object_types{$name}; |
2362 | my $tname = $bcd_types{$type}; |
2445 | my $tname = $bcd_types{$type}; |
2363 | |
2446 | |
2364 | $type = $type ? sprintf "(%08x) %s", $type, $tname : "-"; |
2447 | $type = $type ? sprintf "(%08x) %s", $type, $tname : "-"; |
2365 | |
2448 | |
2366 | printf "%-39s %-23s %s\n", $guid, $name, $type; |
2449 | printf "%-39s %-23s %s\n", $guid, $name, $type; |
… | |
… | |
2380 | BCDE_FORMAT_GUID_LIST , "guid list", |
2463 | BCDE_FORMAT_GUID_LIST , "guid list", |
2381 | BCDE_FORMAT_INTEGER , "integer", |
2464 | BCDE_FORMAT_INTEGER , "integer", |
2382 | BCDE_FORMAT_BOOLEAN , "boolean", |
2465 | BCDE_FORMAT_BOOLEAN , "boolean", |
2383 | BCDE_FORMAT_INTEGER_LIST, "integer list", |
2466 | BCDE_FORMAT_INTEGER_LIST, "integer list", |
2384 | ); |
2467 | ); |
2385 | my %rbcde = reverse %bcde; |
|
|
2386 | $_ = sprintf "%08x", $_ for values %rbcde; |
|
|
2387 | |
2468 | |
2388 | my %element; |
2469 | my %element; |
2389 | |
2470 | |
|
|
2471 | for my $class (sort keys %rbcde_byclass) { |
|
|
2472 | my $rbcde = $rbcde_byclass{$class}; |
|
|
2473 | |
2390 | unless ($json) { |
2474 | unless ($json) { |
2391 | print "\n"; |
2475 | print "\n"; |
|
|
2476 | printf "Elements applicable to class(es): $class\n"; |
2392 | printf "%-9s %-12s %s\n", "Element", "Format", "Name Alias"; |
2477 | printf "%-9s %-12s %s\n", "Element", "Format", "Name Alias"; |
2393 | } |
2478 | } |
2394 | for my $name (sort keys %rbcde) { |
2479 | for my $name (sort keys %$rbcde) { |
2395 | my $id = $rbcde{$name}; |
2480 | my $id = $rbcde->{$name}; |
2396 | my $format = $format_name{(hex $id) & BCDE_FORMAT}; |
2481 | my $format = $format_name{$id & BCDE_FORMAT}; |
|
|
2482 | $id = sprintf "%08x", $id; |
2397 | |
2483 | |
2398 | if ($json) { |
2484 | if ($json) { |
2399 | $element{$id} = [$format, $name]; |
2485 | $element{$id} = [$class, $format, $name]; |
2400 | } else { |
2486 | } else { |
2401 | printf "%-9s %-12s %s\n", $id, $format, $name; |
2487 | printf "%-9s %-12s %s\n", $id, $format, $name; |
|
|
2488 | } |
2402 | } |
2489 | } |
2403 | } |
2490 | } |
2404 | print "\n" unless $json; |
2491 | print "\n" unless $json; |
2405 | |
2492 | |
2406 | prjson { |
2493 | prjson { |
2407 | version => $JSON_VERSION, |
2494 | version => $JSON_VERSION, |
2408 | element => \%element, |
2495 | element => \%element, |
|
|
2496 | class => \@bcde_typeclass, |
2409 | } if $json; |
2497 | } if $json; |
2410 | |
2498 | |
2411 | }, |
2499 | }, |
2412 | |
2500 | |
2413 | export => sub { |
2501 | export => sub { |
… | |
… | |
2465 | } |
2553 | } |
2466 | } |
2554 | } |
2467 | } |
2555 | } |
2468 | } |
2556 | } |
2469 | }, |
2557 | }, |
|
|
2558 | |
|
|
2559 | version => sub { |
|
|
2560 | print "\n", |
|
|
2561 | "PBCDEDIT version $VERSION, copyright 2019 Marc A. Lehmann <pbcdedit\@schmorp.de>.\n", |
|
|
2562 | "JSON schema version: $JSON_VERSION\n", |
|
|
2563 | "Licensed under the GNU General Public License Version 3.0, or any later version.\n", |
|
|
2564 | "\n", |
|
|
2565 | $CHANGELOG, |
|
|
2566 | "\n"; |
|
|
2567 | }, |
2470 | ); |
2568 | ); |
2471 | |
2569 | |
2472 | my $cmd = shift; |
2570 | my $cmd = shift; |
2473 | |
2571 | |
2474 | unless (exists $CMD{$cmd}) { |
2572 | unless (exists $CMD{$cmd}) { |