… | |
… | |
17 | # |
17 | # |
18 | # You should have received a copy of the GNU General Public License |
18 | # You should have received a copy of the GNU General Public License |
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.014; # numerous features needed |
22 | use 5.016; # numerous features need 5.14, __SUB__ needs 5.16 |
23 | |
23 | |
24 | our $VERSION = '1.0'; |
24 | our $VERSION = '1.0'; |
25 | our $JSON_VERSION = 1; # the versiobn of the json objects generated by this program |
25 | our $JSON_VERSION = 1; # the versiobn of the json objects generated by this program |
26 | |
26 | |
27 | =head1 NAME |
27 | =head1 NAME |
… | |
… | |
29 | pbcdedit - portable boot configuration data (BCD) store editor |
29 | pbcdedit - portable boot configuration data (BCD) store editor |
30 | |
30 | |
31 | =head1 SYNOPSIS |
31 | =head1 SYNOPSIS |
32 | |
32 | |
33 | pbcdedit help # output manual page |
33 | pbcdedit help # output manual page |
|
|
34 | |
34 | pbcdedit export path/to/BCD # output BCD hive as JSON |
35 | pbcdedit export path/to/BCD # output BCD hive as JSON |
35 | pbcdedit import path/to/bcd # convert standard input to BCD hive |
36 | pbcdedit import path/to/BCD # convert standard input to BCD hive |
36 | pbcdedit edit path/to/BCD edit-instructions... |
37 | pbcdedit edit path/to/BCD edit-instructions... |
37 | |
38 | |
38 | pbcdedit objects # list all supported object aliases and types |
39 | pbcdedit objects # list all supported object aliases and types |
39 | pbcdedit elements # list all supported bcd element aliases |
40 | pbcdedit elements # list all supported bcd element aliases |
40 | |
41 | |
… | |
… | |
58 | |
59 | |
59 | =item Does not rely on Windows |
60 | =item Does not rely on Windows |
60 | |
61 | |
61 | As the "portable" in the name implies, this program does not rely on |
62 | As the "portable" in the name implies, this program does not rely on |
62 | C<bcdedit> or other windows programs or libraries, it works on any system |
63 | C<bcdedit> or other windows programs or libraries, it works on any system |
63 | that supports at least perl version 5.14. |
64 | that supports at least perl version 5.16. |
64 | |
65 | |
65 | =item Decodes and encodes BCD device elements |
66 | =item Decodes and encodes BCD device elements |
66 | |
67 | |
67 | PBCDEDIT can concisely decode and encode BCD device element contents. This |
68 | PBCDEDIT can concisely decode and encode BCD device element contents. This |
68 | is pretty unique, and offers a lot of potential that can't be realised |
69 | is pretty unique, and offers a lot of potential that can't be realised |
… | |
… | |
75 | sensitive data. |
76 | sensitive data. |
76 | |
77 | |
77 | =back |
78 | =back |
78 | |
79 | |
79 | The target audience for this program is professionals and tinkerers who |
80 | The target audience for this program is professionals and tinkerers who |
80 | are rewady to invest time into learning how it works. It is not an easy |
81 | are ready to invest time into learning how it works. It is not an easy |
81 | program to use and requires patience and a good understanding of BCD data |
82 | program to use and requires patience and a good understanding of BCD |
82 | stores. |
83 | stores. |
83 | |
84 | |
84 | |
85 | |
85 | =head1 SUBCOMMANDS |
86 | =head1 SUBCOMMANDS |
86 | |
87 | |
87 | PCBEDIT expects a subcommand as first argument that tells it what to |
88 | PBCDEDIT expects a subcommand as first argument that tells it what to |
88 | do. The following subcommands exist: |
89 | do. The following subcommands exist: |
89 | |
90 | |
90 | =over |
91 | =over |
91 | |
92 | |
92 | =item help |
93 | =item C<help> |
93 | |
94 | |
94 | Displays the whole manuale page (this document). |
95 | Displays the whole manual page (this document). |
95 | |
96 | |
96 | =item export F<path> |
97 | =item C<export> F<path> |
97 | |
98 | |
98 | Reads a BCD data store and writes a JSON representation of it to standard |
99 | Reads a BCD data store and writes a JSON representation of it to standard |
99 | output. |
100 | output. |
100 | |
101 | |
101 | The format of the data is explained later in this document. |
102 | The format of the data is explained later in this document. |
102 | |
103 | |
103 | Example: read a BCD store, modify it wiht an extenral program, write it again. |
104 | Example: read a BCD store, modify it with an external program, write it |
|
|
105 | again. |
104 | |
106 | |
105 | pbcdedit export BCD | modify-json-somehow | pbcdedit import BCD |
107 | pbcdedit export BCD | modify-json-somehow | pbcdedit import BCD |
106 | |
108 | |
107 | =item import F<path> |
109 | =item C<import> F<path> |
108 | |
110 | |
109 | The reverse of C<export>: Reads a JSON representation of a BCD data store |
111 | The reverse of C<export>: Reads a JSON representation of a BCD data store |
110 | from standard input, and creates or replaces the given BCD data store. |
112 | from standard input, and creates or replaces the given BCD data store. |
111 | |
113 | |
112 | =item edit F<path> instructions... |
114 | =item C<edit> F<path> I<instructions...> |
113 | |
115 | |
114 | Load a BCD data store, apply some instructions to it, and save it again. |
116 | Load a BCD data store, apply some instructions to it, and save it again. |
115 | |
117 | |
116 | See the section L<EDITING BCD DATA STORES>, below, for more info. |
118 | See the section L<EDITING BCD STORES>, below, for more info. |
117 | |
119 | |
118 | =item parse F<path> instructions... |
120 | =item C<parse> F<path> I<instructions...> |
119 | |
121 | |
120 | Same as C<edit>, above, except it doesn't save the data store again. Can |
122 | Same as C<edit>, above, except it doesn't save the data store again. Can |
121 | be useful to extract some data from it. |
123 | be useful to extract some data from it. |
122 | |
124 | |
123 | =item lsblk |
125 | =item C<lsblk> |
124 | |
126 | |
125 | On a GNU/Linux system, you can get a list of partition device descriptors |
127 | On a GNU/Linux system, you can get a list of partition device descriptors |
126 | using this command - the external C<lsblk> command is required, as well as |
128 | using this command - the external C<lsblk> command is required, as well as |
127 | a mounted C</sys> file system. |
129 | a mounted C</sys> file system. |
128 | |
130 | |
129 | The output will be a list of all partitions in the system and C<partition> |
131 | The output will be a list of all partitions in the system and C<partition> |
130 | descriptors for GPT and both C<legacypartition> and C<partition> |
132 | descriptors for GPT and both C<legacypartition> and C<partition> |
131 | descritpors for MBR partitions. |
133 | descriptors for MBR partitions. |
132 | |
134 | |
133 | =item objects [--json] |
135 | =item C<objects> [C<--json>] |
134 | |
136 | |
135 | Outputs two tables: a table listing all type aliases with their hex bcd |
137 | Outputs two tables: a table listing all type aliases with their hex BCD |
136 | element ID, and all object name aliases with their GUID and default type |
138 | element ID, and all object name aliases with their GUID and default type |
137 | (if any). |
139 | (if any). |
138 | |
140 | |
139 | With C<--json> it prints similar information as a JSON object, for easier parsing. |
141 | With C<--json> it prints similar information as a JSON object, for easier parsing. |
140 | |
142 | |
141 | =item elements [--json] |
143 | =item C<elements> [C<--json>] |
142 | |
144 | |
143 | Outputs a table of known element aliases with their hex ID and the format |
145 | Outputs a table of known element aliases with their hex ID and the format |
144 | type. |
146 | type. |
145 | |
147 | |
146 | With C<--json> it prints similar information as a JSON object, for easier parsing. |
148 | With C<--json> it prints similar information as a JSON object, for easier parsing. |
147 | |
149 | |
148 | =item export-regf F<path> |
150 | =item C<export-regf> F<path> |
149 | |
151 | |
150 | This has nothing to do with BCD data stores - it takes a registry hive |
152 | This has nothing to do with BCD stores, but simply exposes PCBEDIT's |
|
|
153 | internal registry hive reader - it takes a registry hive file as argument |
151 | file as argument and outputs a JSON representation of it to standard |
154 | and outputs a JSON representation of it to standard output. |
152 | output. |
|
|
153 | |
155 | |
154 | Hive versions 1.2 till 1.6 are supported. |
156 | Hive versions 1.2 till 1.6 are supported. |
155 | |
157 | |
156 | =item import-regf F<path> |
158 | =item C<import-regf> F<path> |
157 | |
159 | |
158 | The reverse of C<export-regf>: reads a JSON representation of a registry |
160 | The reverse of C<export-regf>: reads a JSON representation of a registry |
159 | hive from standard input and creates or replaces the registry hive file given as |
161 | hive from standard input and creates or replaces the registry hive file |
160 | argument. |
162 | given as argument. |
161 | |
163 | |
162 | The written hive will always be in a slightly modified version 1.3 |
164 | The written hive will always be in a slightly modified version 1.3 |
163 | format. It's not the format windows would generate, but it should be |
165 | format. It's not the format windows would generate, but it should be |
164 | understood by any conformant hive reader. |
166 | understood by any conformant hive reader. |
165 | |
167 | |
166 | Note that the representation chosen by PBCDEDIT currently throws away |
168 | Note that the representation chosen by PBCDEDIT currently throws away |
167 | clasname data (often used for feeble attemtps at hiding stuff by |
169 | classname data (often used for feeble attempts at hiding stuff by |
168 | Microsoft) and security descriptors, so if you write anything other than |
170 | Microsoft) and security descriptors, so if you write anything other than |
169 | a BCD hive you will most likely destroy it. |
171 | a BCD hive you will most likely destroy it. |
170 | |
172 | |
171 | =back |
173 | =back |
172 | |
174 | |
173 | |
175 | |
174 | =head1 BCD DATA STORE REPRESENTATION FORMAT |
176 | =head1 BCD STORE REPRESENTATION FORMAT |
175 | |
177 | |
176 | A BCD data store is represented as a JSON object with one special key, |
178 | A BCD data store is represented as a JSON object with one special key, |
177 | C<meta>, and one key per BCD object. That is, each BCD object becomes |
179 | C<meta>, and one key per BCD object. That is, each BCD object becomes |
178 | one key-value pair in the object, and an additional key called C<meta> |
180 | one key-value pair in the object, and an additional key called C<meta> |
179 | contains meta information. |
181 | contains meta information. |
… | |
… | |
242 | =head2 The C<meta> key |
244 | =head2 The C<meta> key |
243 | |
245 | |
244 | The C<meta> key is not stored in the BCD data store but is used only |
246 | The C<meta> key is not stored in the BCD data store but is used only |
245 | by PBCDEDIT. It is always generated when exporting, and importing will |
247 | by PBCDEDIT. It is always generated when exporting, and importing will |
246 | be refused when it exists and the version stored inside doesn't store |
248 | be refused when it exists and the version stored inside doesn't store |
247 | the JSON schema version of PBCDEDIT. This ensures that differemt and |
249 | the JSON schema version of PBCDEDIT. This ensures that different and |
248 | incompatible versions of PBCDEDIT will not read and misinterΓΌret each |
250 | incompatible versions of PBCDEDIT will not read and misinterpret each |
249 | others data. |
251 | others data. |
250 | |
252 | |
251 | =head2 The object keys |
253 | =head2 The object keys |
252 | |
254 | |
253 | Every other key is a BCD object. There is usually a BCD object for the |
255 | Every other key is a BCD object. There is usually a BCD object for the |
254 | boot manager, one for every boot option and a few others that store common |
256 | boot manager, one for every boot option and a few others that store common |
255 | settings inherited by these. |
257 | settings inherited by these. |
256 | |
258 | |
257 | Each BCD object is represented by a GUID wrapped in curly braces. These |
259 | Each BCD object is represented by a GUID wrapped in curly braces. These |
258 | are usually random GUIDs used only to distinguish bCD objects from each |
260 | are usually random GUIDs used only to distinguish BCD objects from each |
259 | other. When adding a new boot option, you can simply generate a new GUID. |
261 | other. When adding a new boot option, you can simply generate a new GUID. |
260 | |
262 | |
261 | Some of these GUIDs are fixed well known GUIDs which PBCDEDIT will decode |
263 | Some of these GUIDs are fixed well known GUIDs which PBCDEDIT will decode |
262 | into human-readable strings such as C<{globalsettings}>, which is the same |
264 | into human-readable strings such as C<{globalsettings}>, which is the same |
263 | as C<{7ea2e1ac-2e61-4728-aaa3-896d9d0a9f0e}>. |
265 | as C<{7ea2e1ac-2e61-4728-aaa3-896d9d0a9f0e}>. |
… | |
… | |
297 | get a list of all BCD elements known to PBCDEDIT by running F<pbcdedit |
299 | get a list of all BCD elements known to PBCDEDIT by running F<pbcdedit |
298 | elements>. |
300 | elements>. |
299 | |
301 | |
300 | What was said about duplicate keys mapping to the same object is true for |
302 | What was said about duplicate keys mapping to the same object is true for |
301 | elements as well, so, again, you should always use the canonical name, |
303 | elements as well, so, again, you should always use the canonical name, |
302 | whcih is the human radable alias, if known. |
304 | which is the human readable alias, if known. |
303 | |
305 | |
304 | =head3 BCD element types |
306 | =head3 BCD element types |
305 | |
307 | |
306 | Each BCD element has a type such as I<string> or I<boolean>. This type |
308 | Each BCD element has a type such as I<string> or I<boolean>. This type |
307 | determines how the value is interpreted, and most of them are pretty easy |
309 | determines how the value is interpreted, and most of them are pretty easy |
… | |
… | |
319 | "description" : "Windows 10", |
321 | "description" : "Windows 10", |
320 | "systemroot" : "\\Windows", |
322 | "systemroot" : "\\Windows", |
321 | |
323 | |
322 | =item boolean |
324 | =item boolean |
323 | |
325 | |
324 | Almost as simnple are booleans, which represent I<true>/I<false>, |
326 | Almost as simple are booleans, which represent I<true>/I<false>, |
325 | I<on>/I<off> and similar values. In the JSON form, true is represented |
327 | I<on>/I<off> and similar values. In the JSON form, true is represented |
326 | by the number C<1>, and false is represented by the number C<0>. Other |
328 | by the number C<1>, and false is represented by the number C<0>. Other |
327 | values will be accepted, but PBCDEDIT doesn't guarantee how these are |
329 | values will be accepted, but PBCDEDIT doesn't guarantee how these are |
328 | interpreted. |
330 | interpreted. |
329 | |
331 | |
… | |
… | |
335 | |
337 | |
336 | =item integer |
338 | =item integer |
337 | |
339 | |
338 | Again, very simple, this is a 64 bit integer. IT can be either specified |
340 | Again, very simple, this is a 64 bit integer. IT can be either specified |
339 | as a decimal number, as a hex number (by prefixing it with C<0x>) or as a |
341 | as a decimal number, as a hex number (by prefixing it with C<0x>) or as a |
340 | binatry number (prefix C<0b>). |
342 | binary number (prefix C<0b>). |
341 | |
343 | |
342 | For example, the boot C<timeout> is an integer, specifying the automatic |
344 | For example, the boot C<timeout> is an integer, specifying the automatic |
343 | boot delay in seconds: |
345 | boot delay in seconds: |
344 | |
346 | |
345 | "timeout" : 30, |
347 | "timeout" : 30, |
346 | |
348 | |
347 | =item integer list |
349 | =item integer list |
348 | |
350 | |
349 | This is a list of 64 bit integers separated by whitespace. It is not used |
351 | This is a list of 64 bit integers separated by whitespace. It is not used |
350 | much, so here is a somewhat artificial an untested exanmple of using |
352 | much, so here is a somewhat artificial an untested example of using |
351 | C<customactions> to specify a certain custom, eh, action to be executed |
353 | C<customactions> to specify a certain custom, eh, action to be executed |
352 | when pressing C<F10> at boot: |
354 | when pressing C<F10> at boot: |
353 | |
355 | |
354 | "customactions" : "0x1000044000001 0x54000001", |
356 | "customactions" : "0x1000044000001 0x54000001", |
355 | |
357 | |
356 | =item guid |
358 | =item guid |
357 | |
359 | |
358 | This represents a single GUID value wrqapped in curly braces. It is used a |
360 | This represents a single GUID value wrapped in curly braces. It is used a |
359 | lot to refer from one BCD object to other one. |
361 | lot to refer from one BCD object to other one. |
360 | |
362 | |
361 | For example, The C<{bootmgr}> object might refer to a resume boot option |
363 | For example, The C<{bootmgr}> object might refer to a resume boot option |
362 | using C<resumeobject>: |
364 | using C<resumeobject>: |
363 | |
365 | |
… | |
… | |
365 | |
367 | |
366 | Human readable aliases are used and allowed. |
368 | Human readable aliases are used and allowed. |
367 | |
369 | |
368 | =item guid list |
370 | =item guid list |
369 | |
371 | |
370 | Similar to te guid type, this represents a list of such GUIDs, separated |
372 | Similar to the GUID type, this represents a list of such GUIDs, separated |
371 | by whitespace from each other. |
373 | by whitespace from each other. |
372 | |
374 | |
373 | For example, many BCD objects can I<inherit> elements from other BCD |
375 | For example, many BCD objects can I<inherit> elements from other BCD |
374 | objects by specifying the GUIDs of those other objects ina GUID list |
376 | objects by specifying the GUIDs of those other objects in a GUID list |
375 | called surprisingly called C<inherit>: |
377 | called surprisingly called C<inherit>: |
376 | |
378 | |
377 | "inherit" : "{dbgsettings} {emssettings} {badmemory}", |
379 | "inherit" : "{dbgsettings} {emssettings} {badmemory}", |
378 | |
380 | |
379 | This example also shows how human readable aliases can be used. |
381 | This example also shows how human readable aliases can be used. |
… | |
… | |
388 | =back |
390 | =back |
389 | |
391 | |
390 | =head4 The BCD "device" element type |
392 | =head4 The BCD "device" element type |
391 | |
393 | |
392 | Device elements specify, well, devices. They are used for such diverse |
394 | Device elements specify, well, devices. They are used for such diverse |
393 | purposes such as finding a TFTP network boot imagem serial ports or VMBUS |
395 | purposes such as finding a TFTP network boot image, serial ports or VMBUS |
394 | devices, but most commonly they are used to specify the disk (harddisk, |
396 | devices, but most commonly they are used to specify the disk (harddisk, |
395 | cdrom ramdisk, vhd...) to boot from. |
397 | cdrom, ramdisk, vhd...) to boot from. |
396 | |
398 | |
397 | The device element is kind of a mini-language in its own which is much |
399 | The device element is kind of a mini-language in its own which is much |
398 | more versatile then the limited windows interface to it - BCDEDIT - |
400 | more versatile then the limited windows interface to it - BCDEDIT - |
399 | reveals. |
401 | reveals. |
400 | |
402 | |
… | |
… | |
403 | element, so almost everything known about it had to be researched first |
405 | element, so almost everything known about it had to be researched first |
404 | in the process of writing this script, and consequently, support for BCD |
406 | in the process of writing this script, and consequently, support for BCD |
405 | device elements is partial only. |
407 | device elements is partial only. |
406 | |
408 | |
407 | On the other hand, the expressive power of PBCDEDIT in specifying devices |
409 | On the other hand, the expressive power of PBCDEDIT in specifying devices |
408 | is much bigger than BCDEDIT and therefore more cna be don with it. The |
410 | is much bigger than BCDEDIT and therefore more can be done with it. The |
409 | downside is that BCD device elements are much more complicated than what |
411 | downside is that BCD device elements are much more complicated than what |
410 | you might think from reading the BCDEDIT documentation. |
412 | you might think from reading the BCDEDIT documentation. |
411 | |
413 | |
412 | In other words, simple things are complicated, and complicated things are |
414 | In other words, simple things are complicated, and complicated things are |
413 | possible. |
415 | possible. |
414 | |
416 | |
415 | Anyway, the general syntax of device elements is an optional GUID, |
417 | Anyway, the general syntax of device elements is an optional GUID, |
416 | followed by a device type, optionally followed by hexdecimal flags in |
418 | followed by a device type, optionally followed by hexadecimal flags in |
417 | angle brackets, optionally followed by C<=> and a comma-separated list of |
419 | angle brackets, optionally followed by C<=> and a comma-separated list of |
418 | arguments, some of which can be (and often are) in turn devices again. |
420 | arguments, some of which can be (and often are) in turn devices again. |
419 | |
421 | |
420 | [{GUID}]type[<flags>][=arg,arg...] |
422 | [{GUID}]type[<flags>][=arg,arg...] |
421 | |
423 | |
… | |
… | |
447 | The types understood and used by PBCDEDIT are as follows (keep in mind |
449 | The types understood and used by PBCDEDIT are as follows (keep in mind |
448 | that not of all the following is necessarily supported in PBCDEDIT): |
450 | that not of all the following is necessarily supported in PBCDEDIT): |
449 | |
451 | |
450 | =over |
452 | =over |
451 | |
453 | |
452 | =item binary=hex... |
454 | =item C<binary=>I<hex...> |
453 | |
455 | |
454 | This type isn't actually a real BCD element type, but a fallback for those |
456 | This type isn't actually a real BCD element type, but a fallback for those |
455 | cases where PBCDEDIT can't perfectly decode a device element (except for |
457 | cases where PBCDEDIT can't perfectly decode a device element (except for |
456 | the leading GUID, which it can always decode). In such cases, it will |
458 | the leading GUID, which it can always decode). In such cases, it will |
457 | convert the device into this type with a hexdump of the element data. |
459 | convert the device into this type with a hexdump of the element data. |
458 | |
460 | |
459 | =item null |
461 | =item C<null> |
460 | |
462 | |
461 | This is another special type - sometimes, a device all zero-filled, which |
463 | This is another special type - sometimes, a device all zero-filled, which |
462 | is not valid. This can mark the absence of a device or something PBCDEDIT |
464 | is not valid. This can mark the absence of a device or something PBCDEDIT |
463 | does not understand, so it decodes it into this special "all zero" type |
465 | does not understand, so it decodes it into this special "all zero" type |
464 | called C<null>. |
466 | called C<null>. |
465 | |
467 | |
466 | It's most commonly found in devices that can use an optional parent |
468 | It's most commonly found in devices that can use an optional parent |
467 | device, when no parent device is used. |
469 | device, when no parent device is used. |
468 | |
470 | |
469 | =item boot |
471 | =item C<boot> |
470 | |
472 | |
471 | Another type without parameters, this refers to the device that was booted |
473 | Another type without parameters, this refers to the device that was booted |
472 | from (nowadays typically the EFI system partition). |
474 | from (nowadays typically the EFI system partition). |
473 | |
475 | |
474 | =item vmbus=interfacetype,interfaceinstance |
476 | =item C<vmbus=>I<interfacetype>,I<interfaceinstance> |
475 | |
477 | |
476 | This specifies a VMBUS device with the given interface type and interface |
478 | This specifies a VMBUS device with the given interface type and interface |
477 | instance, both of which are "naked" (no curly braces) GUIDs. |
479 | instance, both of which are "naked" (no curly braces) GUIDs. |
478 | |
480 | |
479 | Made-up example (couldn't find a single example on the web): |
481 | Made-up example (couldn't find a single example on the web): |
480 | |
482 | |
481 | vmbus=c376c1c3-d276-48d2-90a9-c04748072c60,12345678-a234-b234-c234-d2345678abcd |
483 | vmbus=c376c1c3-d276-48d2-90a9-c04748072c60,12345678-a234-b234-c234-d2345678abcd |
482 | |
484 | |
483 | =item partition=<parent>,devicetype,partitiontype,diskid,partitionid |
485 | =item C<partition=><I<parent>>,I<devicetype>,I<partitiontype>,I<diskid>,I<partitionid> |
484 | |
486 | |
485 | This designates a specific partition on a block device. C<< <parent> |
487 | This designates a specific partition on a block device. I<parent> is an |
486 | >> is an optional parent device on which to search on, and is often |
488 | optional parent device on which to search on, and is often C<null>. Note |
487 | C<null>. Note that the anfgle brackets are part of the syntax. |
489 | that the angle brackets around I<parent> are part of the syntax. |
488 | |
490 | |
489 | C<devicetypes> is one of C<harddisk>, C<floppy>, C<cdrom>, C<ramdisk>, |
491 | I<devicetypes> is one of C<harddisk>, C<floppy>, C<cdrom>, C<ramdisk>, |
490 | C<file> or C<vhd>, where the first three should be self-explaining, |
492 | C<file> or C<vhd>, where the first three should be self-explaining, |
491 | C<file> is usually used to locate a device by finding a magic file, and |
493 | C<file> is usually used to locate a file to be used as a disk image, |
492 | C<vhd> is used for virtual harddisks - F<.vhd> and F<-vhdx> files. |
494 | and C<vhd> is used to treat files as virtual harddisks, i.e. F<vhd> and |
|
|
495 | F<vhdx> files. |
493 | |
496 | |
494 | The C<partitiontype> is either C<mbr>, C<gpt> or C<raw>, the latter being |
497 | The I<partitiontype> is either C<mbr>, C<gpt> or C<raw>, the latter being |
495 | used for devices without partitions, such as cdroms, where the "partition" |
498 | used for devices without partitions, such as cdroms, where the "partition" |
496 | is usually the whole device. |
499 | is usually the whole device. |
497 | |
500 | |
498 | The C<diskid> identifies the disk or device using a unique signature, and |
501 | The I<diskid> identifies the disk or device using a unique signature, and |
499 | the same is true for the C<partitionid>. How these are interpreted depends |
502 | the same is true for the I<partitionid>. How these are interpreted depends |
500 | on the C<partitiontype>: |
503 | on the I<partitiontype>: |
501 | |
504 | |
502 | =over |
505 | =over |
503 | |
506 | |
504 | =item mbr |
507 | =item C<mbr> |
505 | |
508 | |
506 | The C<diskid> is the 32 bit disk signature stored at offset 0x1b8 in the |
509 | The C<diskid> is the 32 bit disk signature stored at offset 0x1b8 in the |
507 | MBR, interpreted as a 32 bit unsigned little endian integer and written as |
510 | MBR, interpreted as a 32 bit unsigned little endian integer and written as |
508 | hex number. That is, the bytes C<01 02 03 04> would become C<04030201>. |
511 | hex number. That is, the bytes C<01 02 03 04> would become C<04030201>. |
509 | |
512 | |
510 | Diskpart (using the C<DETAIL> command) and the C<lsblk> comamnd typically |
513 | Diskpart (using the C<DETAIL> command) and the C<lsblk> command typically |
511 | found on GNU/Linux systems (using e.g. C<lsblk -o NAME,PARTUUID>) can |
514 | found on GNU/Linux systems (using e.g. C<lsblk -o NAME,PARTUUID>) can |
512 | display the disk id. |
515 | display the I<diskid>. |
513 | |
516 | |
514 | The C<partitionid> is the byte offset(!) of the partition counting from |
517 | The I<partitionid> is the byte offset(!) of the partition counting from |
515 | the beginning of the MBR. |
518 | the beginning of the MBR. |
516 | |
519 | |
517 | Example, use the partition on the harddisk with C<diskid> C<47cbc08a> |
520 | Example, use the partition on the harddisk with I<diskid> C<47cbc08a> |
518 | starting at sector C<2048> (= 1048576 / 512). |
521 | starting at sector C<2048> (= 1048576 / 512). |
519 | |
522 | |
520 | partition=<null>,harddisk,mbr,47cbc08a,1048576 |
523 | partition=<null>,harddisk,mbr,47cbc08a,1048576 |
521 | |
524 | |
522 | =item gpt |
525 | =item C<gpt> |
523 | |
526 | |
524 | The C<diskid> is the disk UUID/disk identifier GUID from the partition |
527 | The I<diskid> is the disk GUID/disk identifier GUID from the partition |
525 | table (as displayed e.g. by C<gdisk>), and the C<partitionid> is the |
528 | table (as displayed e.g. by F<gdisk>), and the I<partitionid> is the |
526 | partition unique GUID (displayed using e.g. the C<gdisk> C<i> command). |
529 | partition unique GUID (displayed using e.g. the F<gdisk> F<i> command). |
527 | |
530 | |
528 | Example: use the partition C<76d39e5f-ad1b-407e-9c05-c81eb83b57dd> on GPT |
531 | Example: use the partition C<76d39e5f-ad1b-407e-9c05-c81eb83b57dd> on GPT |
529 | disk C<9742e468-9206-48a0-b4e4-c4e9745a356a>. |
532 | disk C<9742e468-9206-48a0-b4e4-c4e9745a356a>. |
530 | |
533 | |
531 | partition=<null>,harddisk,gpt,9742e468-9206-48a0-b4e4-c4e9745a356a,76d39e5f-ad1b-407e-9c05-c81eb83b57dd |
534 | partition=<null>,harddisk,gpt,9742e468-9206-48a0-b4e4-c4e9745a356a,76d39e5f-ad1b-407e-9c05-c81eb83b57dd |
532 | |
535 | |
533 | =item raw |
536 | =item C<raw> |
534 | |
537 | |
535 | Instead of diskid and partitionid, this type only accepts a decimal disk |
538 | Instead of I<diskid> and I<partitionid>, this type only accepts a decimal |
536 | number and signifies the whole disk. BCDEDIT cannot display the resulting |
539 | disk number and signifies the whole disk. BCDEDIT cannot display the |
537 | device, and I am doubtful whether it has a useful effect. |
540 | resulting device, and I am doubtful whether it has a useful effect. |
538 | |
541 | |
539 | =back |
542 | =back |
540 | |
543 | |
541 | =item legacypartition=<parent>,devicetype,partitiontype,diskid,partitionid |
544 | =item C<legacypartition=><I<parent>>,I<devicetype>,I<partitiontype>,I<diskid>,I<partitionid> |
542 | |
545 | |
543 | This is exactly the same as the C<partition> type, except for a tiny |
546 | This is exactly the same as the C<partition> type, except for a tiny |
544 | detail: instead of using the partition start offset, this type uses the |
547 | detail: instead of using the partition start offset, this type uses the |
545 | partition number for MBR disks. Behaviour other partition types should be |
548 | partition number for MBR disks. Behaviour other partition types should be |
546 | the same. |
549 | the same. |
547 | |
550 | |
548 | The partition number starts at C<1> and skips unused partition, so if |
551 | The partition number starts at C<1> and skips unused partition, so if |
549 | there are two primary partitions and another partition inside the extended |
552 | there are two primary partitions and another partition inside the extended |
550 | partition, the primary partitions are number C<1> and C<2> and the |
553 | partition, the primary partitions are number C<1> and C<2> and the |
551 | partition inside the extended partition is number C<3>, rwegardless of any |
554 | partition inside the extended partition is number C<3>, regardless of any |
552 | gaps. |
555 | gaps. |
553 | |
556 | |
554 | =item locate=<parent>,locatetype,locatearg |
557 | =item C<locate=><I<parent>>,I<locatetype>,I<locatearg> |
555 | |
558 | |
556 | This device description will make the bootloader search for a partition |
559 | This device description will make the bootloader search for a partition |
557 | with a given path. |
560 | with a given path. |
558 | |
561 | |
559 | The C<< <parent> >> device is the device to search on (angle brackets are |
562 | The I<parent> device is the device to search on (angle brackets are |
560 | still part of the syntax!) If it is C<< <null> >>, then C<locate> will |
563 | still part of the syntax!) If it is C<null>, then C<locate> will |
561 | search all disks it can find. |
564 | search all disks it can find. |
562 | |
565 | |
563 | C<locatetype> is either C<element> or C<path>, and merely distinguishes |
566 | I<locatetype> is either C<element> or C<path>, and merely distinguishes |
564 | between two different ways to specify the path to search for: C<element> |
567 | between two different ways to specify the path to search for: C<element> |
565 | uses an element ID (either as hex or as name) as C<locatearg> and C<path> |
568 | uses an element ID (either as hex or as name) as I<locatearg> and C<path> |
566 | uses a relative path as C<locatearg>. |
569 | uses a relative path as I<locatearg>. |
567 | |
570 | |
568 | Example: find any partition which has the C<magicfile.xxx> path in the |
571 | Example: find any partition which has the F<magicfile.xxx> path in the |
569 | root. |
572 | root. |
570 | |
573 | |
571 | locate=<null>,path,\magicfile.xxx |
574 | locate=<null>,path,\magicfile.xxx |
572 | |
575 | |
573 | Example: find any partition which has the path specified in the |
576 | Example: find any partition which has the path specified in the |
574 | C<systemroot> element (typically C<\Windows>). |
577 | C<systemroot> element (typically F<\Windows>). |
575 | |
578 | |
576 | locate=<null>,element,systemroot |
579 | locate=<null>,element,systemroot |
577 | |
580 | |
578 | =item block=devicetype,args... |
581 | =item C<block=>I<devicetype>,I<args...> |
579 | |
582 | |
580 | Last not least, the most complex type, C<block>, which... specifies block |
583 | Last not least, the most complex type, C<block>, which... specifies block |
581 | devices (which could be inside a F<vhdx> file for example). |
584 | devices (which could be inside a F<vhdx> file for example). |
582 | |
585 | |
583 | C<devicetypes> is one of C<harddisk>, C<floppy>, C<cdrom>, C<ramdisk>, |
586 | I<devicetypes> is one of C<harddisk>, C<floppy>, C<cdrom>, C<ramdisk>, |
584 | C<file> or C<vhd> - the same as for C<partiion=>. |
587 | C<file> or C<vhd> - the same as for C<partiion=>. |
585 | |
588 | |
586 | The remaining arguments change depending on the C<devicetype>: |
589 | The remaining arguments change depending on the I<devicetype>: |
587 | |
590 | |
588 | =over |
591 | =over |
589 | |
592 | |
590 | =item block=file,<parent>,path |
593 | =item C<block=file>,<I<parent>>,I<path> |
591 | |
594 | |
592 | Interprets the C<< <parent> >> device (typically a partition) as a |
595 | Interprets the I<parent> device (typically a partition) as a |
593 | filesystem and specifies a file path inside. |
596 | filesystem and specifies a file path inside. |
594 | |
597 | |
595 | =item block=vhd,<parent> |
598 | =item C<block=vhd>,<I<parent>> |
596 | |
599 | |
597 | Pretty much just changes the interpretation of C<< <parent> >>, which is |
600 | Pretty much just changes the interpretation of I<parent>, which is |
598 | usually a disk image (C<block=file,...)>) to be a F<vhd> or F<vhdx> file. |
601 | usually a disk image (C<block=file,...)>) to be a F<vhd> or F<vhdx> file. |
599 | |
602 | |
600 | =item block=ramdisk,<parent>,base,size,offset,path |
603 | =item C<block=ramdisk>,<I<parent>>,I<base>,I<size>,I<offset>,I<path> |
601 | |
604 | |
602 | Interprets the C<< <parent> >> device as RAM disk, using the (decimal) |
605 | Interprets the I<parent> device as RAM disk, using the (decimal) |
603 | base address, byte size and byte offset inside a file specified by |
606 | base address, byte size and byte offset inside a file specified by |
604 | C<path>. The numbers are usually all C<0> because they cna be extracted |
607 | I<path>. The numbers are usually all C<0> because they can be extracted |
605 | from the RAM disk image or other parameters. |
608 | from the RAM disk image or other parameters. |
606 | |
609 | |
607 | This is most commonly used to boot C<wim> images. |
610 | This is most commonly used to boot C<wim> images. |
608 | |
611 | |
609 | =item block=floppy,drivenum |
612 | =item C<block=floppy>,I<drivenum> |
610 | |
613 | |
611 | Refers to a removable drive identified by a number. BCDEDIT cannot display |
614 | Refers to a removable drive identified by a number. BCDEDIT cannot display |
612 | the resultinfg device, and it is not clear what effect it will have. |
615 | the resulting device, and it is not clear what effect it will have. |
613 | |
616 | |
614 | =item block=cdrom,drivenum |
617 | =item C<block=cdrom>,I<drivenum> |
615 | |
618 | |
616 | Pretty much the same as C<floppy> but for CD-ROMs. |
619 | Pretty much the same as C<floppy> but for CD-ROMs. |
617 | |
620 | |
618 | =item anything else |
621 | =item anything else |
619 | |
622 | |
… | |
… | |
623 | |
626 | |
624 | =back5 Examples |
627 | =back5 Examples |
625 | |
628 | |
626 | This concludes the syntax overview for device elements, but probably |
629 | This concludes the syntax overview for device elements, but probably |
627 | leaves many questions open. I can't help with most of them, as I also ave |
630 | leaves many questions open. I can't help with most of them, as I also ave |
628 | many questions, but I can walk you through some actual examples using mroe |
631 | many questions, but I can walk you through some actual examples using more |
629 | complex aspects. |
632 | complex aspects. |
630 | |
633 | |
631 | =item locate=<block=vhd,<block=file,<locate=<null>,path,\disk.vhdx>,\disk.vhdx>>,element,path |
634 | =item C<< locate=<block=vhd,<block=file,<locate=<null>,path,\disk.vhdx>,\disk.vhdx>>,element,path >> |
632 | |
635 | |
633 | Just like with C declarations, you best treat device descriptors as |
636 | Just like with C declarations, you best treat device descriptors as |
634 | instructions to find your device and work your way from the inside out: |
637 | instructions to find your device and work your way from the inside out: |
635 | |
638 | |
636 | locate=<null>,path,\disk.vhdx |
639 | locate=<null>,path,\disk.vhdx |
… | |
… | |
643 | Next, this takes the device locate has found and finds a file called |
646 | Next, this takes the device locate has found and finds a file called |
644 | F<\disk.vhdx> on it. This is the same file locate was using, but that is |
647 | F<\disk.vhdx> on it. This is the same file locate was using, but that is |
645 | only because we find the device using the same path as finding the disk |
648 | only because we find the device using the same path as finding the disk |
646 | image, so this is purely incidental, although quite common. |
649 | image, so this is purely incidental, although quite common. |
647 | |
650 | |
648 | Bext, this file will be opened as a virtual disk: |
651 | Next, this file will be opened as a virtual disk: |
649 | |
652 | |
650 | block=vhd,<see above> |
653 | block=vhd,<see above> |
651 | |
654 | |
652 | And finally, inside this disk, another C<locate> will look for a partition |
655 | And finally, inside this disk, another C<locate> will look for a partition |
653 | with a path as specified in the C<path> element, which most likely will be |
656 | with a path as specified in the C<path> element, which most likely will be |
… | |
… | |
656 | locate=<see above>,element,path |
659 | locate=<see above>,element,path |
657 | |
660 | |
658 | As a result, this will boot the first Windows it finds on the first |
661 | As a result, this will boot the first Windows it finds on the first |
659 | F<disk.vhdx> disk image it can find anywhere. |
662 | F<disk.vhdx> disk image it can find anywhere. |
660 | |
663 | |
661 | =item locate=<block=vhd,<block=file,<partition=<null>,harddisk,mbr,47cbc08a,242643632128>,\win10.vhdx>>,element,path |
664 | =item C<< locate=<block=vhd,<block=file,<partition=<null>,harddisk,mbr,47cbc08a,242643632128>,\win10.vhdx>>,element,path >> |
662 | |
665 | |
663 | Pretty much the same as the previous case, but witzh a bit of variance. First, look for a specific partition on |
666 | Pretty much the same as the previous case, but with a bit of |
664 | an MBR-partitioned disk: |
667 | variance. First, look for a specific partition on an MBR-partitioned disk: |
665 | |
668 | |
666 | partition=<null>,harddisk,mbr,47cbc08a,242643632128 |
669 | partition=<null>,harddisk,mbr,47cbc08a,242643632128 |
667 | |
670 | |
668 | Then open the file F<\win10.vhdx> on that partition: |
671 | Then open the file F<\win10.vhdx> on that partition: |
669 | |
672 | |
… | |
… | |
675 | |
678 | |
676 | And again the windows loader (or whatever is in C<path>) will be searched: |
679 | And again the windows loader (or whatever is in C<path>) will be searched: |
677 | |
680 | |
678 | locate=<see above>,element,path |
681 | locate=<see above>,element,path |
679 | |
682 | |
680 | =item {b097d2b2-bc00-11e9-8a9a-525400123456}block<1>=ramdisk,<partition=<null>,harddisk,mbr,47cbc08a,242643632128>,0,0,0,\boot.wim |
683 | =item C<< {b097d2b2-bc00-11e9-8a9a-525400123456}block<1>=ramdisk,<partition=<null>,harddisk,mbr,47cbc08a,242643632128>,0,0,0,\boot.wim >> |
681 | |
684 | |
682 | This is quite different. First, it starts with a GUID. This GUID belongs |
685 | This is quite different. First, it starts with a GUID. This GUID belongs |
683 | to a BCD object of type C<device>, which has additional parameters: |
686 | to a BCD object of type C<device>, which has additional parameters: |
684 | |
687 | |
685 | "{b097d2b2-bc00-11e9-8a9a-525400123456}" : { |
688 | "{b097d2b2-bc00-11e9-8a9a-525400123456}" : { |
… | |
… | |
688 | "ramdisksdidevice" : "partition=<null>,harddisk,mbr,47cbc08a,1048576", |
691 | "ramdisksdidevice" : "partition=<null>,harddisk,mbr,47cbc08a,1048576", |
689 | "ramdisksdipath" : "\boot.sdi" |
692 | "ramdisksdipath" : "\boot.sdi" |
690 | }, |
693 | }, |
691 | |
694 | |
692 | I will not go into many details, but this specifies a (presumably empty) |
695 | I will not go into many details, but this specifies a (presumably empty) |
693 | template ramdisk image (F<\boot.sdi>) that is used to initiaolize the |
696 | template ramdisk image (F<\boot.sdi>) that is used to initialize the |
694 | ramdisk. The F<\boot.wim> file is then extracted into it. As you cna also |
697 | ramdisk. The F<\boot.wim> file is then extracted into it. As you can also |
695 | see, this F<.sdi> file resides on a different C<partition>. |
698 | see, this F<.sdi> file resides on a different C<partition>. |
696 | |
699 | |
697 | Continuitn, as always, form the inside out, first this device descriptor |
700 | Continuing, as always, from the inside out, first this device descriptor |
698 | finds a specific partition: |
701 | finds a specific partition: |
699 | |
702 | |
700 | partition=<null>,harddisk,mbr,47cbc08a,242643632128 |
703 | partition=<null>,harddisk,mbr,47cbc08a,242643632128 |
701 | |
704 | |
702 | And then specifies a C<ramdisk> image on this partition: |
705 | And then specifies a C<ramdisk> image on this partition: |
… | |
… | |
707 | seems to be always there on this kind of entry. |
710 | seems to be always there on this kind of entry. |
708 | |
711 | |
709 | If you have some good examples to add here, feel free to mail me. |
712 | If you have some good examples to add here, feel free to mail me. |
710 | |
713 | |
711 | |
714 | |
712 | =head1 EDITING BCD DATA STORES |
715 | =head1 EDITING BCD STORES |
713 | |
716 | |
714 | The C<edit> and C<parse> subcommands allow you to read a BCD data store |
717 | The C<edit> and C<parse> subcommands allow you to read a BCD data store |
715 | and modify it or extract data from it. This is done by exyecuting a series |
718 | and modify it or extract data from it. This is done by executing a series |
716 | of "editing instructions" which are explained here. |
719 | of "editing instructions" which are explained here. |
717 | |
720 | |
718 | =over |
721 | =over |
719 | |
722 | |
720 | =item get I<object> I<element> |
723 | =item C<get> I<object> I<element> |
721 | |
724 | |
722 | Reads the BCD element I<element> from the BCD object I<object> and writes |
725 | Reads the BCD element I<element> from the BCD object I<object> and writes |
723 | it to standard output, followed by a newline. The I<object> can be a GUID |
726 | it to standard output, followed by a newline. The I<object> can be a GUID |
724 | or a human-readable alias, or the special string C<{default}>, which will |
727 | or a human-readable alias, or the special string C<{default}>, which will |
725 | refer to the default BCD object. |
728 | refer to the default BCD object. |
726 | |
729 | |
727 | Example: find description of the default BCD object. |
730 | Example: find description of the default BCD object. |
728 | |
731 | |
729 | pbcdedit parse BCD get "{default}" description |
732 | pbcdedit parse BCD get "{default}" description |
730 | |
733 | |
731 | =item set I<object> I<element> I<value> |
734 | =item C<set> I<object> I<element> I<value> |
732 | |
735 | |
733 | Similar to C<get>, but sets the element to the given I<value> instead. |
736 | Similar to C<get>, but sets the element to the given I<value> instead. |
734 | |
737 | |
735 | Example: change bootmgr default too |
738 | Example: change the bootmgr default too |
736 | C<{b097d2ad-bc00-11e9-8a9a-525400123456}>: |
739 | C<{b097d2ad-bc00-11e9-8a9a-525400123456}>: |
737 | |
740 | |
738 | pbcdedit edit BCD set "{bootmgr}" resumeobject "{b097d2ad-bc00-11e9-8a9a-525400123456}" |
741 | pbcdedit edit BCD set "{bootmgr}" resumeobject "{b097d2ad-bc00-11e9-8a9a-525400123456}" |
739 | |
742 | |
740 | =item eval I<perlcode> |
743 | =item C<eval> I<perlcode> |
741 | |
744 | |
742 | This takes the next argument, interprets it as Perl code and |
745 | This takes the next argument, interprets it as Perl code and |
743 | evaluates it. This allows you to do more complicated modifications or |
746 | evaluates it. This allows you to do more complicated modifications or |
744 | extractions. |
747 | extractions. |
745 | |
748 | |
… | |
… | |
764 | The example given for C<get>, above, could be expressed like this with |
767 | The example given for C<get>, above, could be expressed like this with |
765 | C<eval>: |
768 | C<eval>: |
766 | |
769 | |
767 | pbcdedit edit BCD eval 'say $BCD->{$DEFAULT}{description}' |
770 | pbcdedit edit BCD eval 'say $BCD->{$DEFAULT}{description}' |
768 | |
771 | |
769 | The example given for C<set> could be expresed like this: |
772 | The example given for C<set> could be expressed like this: |
770 | |
773 | |
771 | pbcdedit edit BCD eval '$BCD->{$DEFAULT}{resumeobject} = "{b097d2ad-bc00-11e9-8a9a-525400123456}"' |
774 | pbcdedit edit BCD eval '$BCD->{$DEFAULT}{resumeobject} = "{b097d2ad-bc00-11e9-8a9a-525400123456}"' |
772 | |
775 | |
773 | =item do I<path> |
776 | =item C<do> I<path> |
774 | |
777 | |
775 | Similar to C<eval>, above, but instead of using the argument as perl code, |
778 | Similar to C<eval>, above, but instead of using the argument as perl code, |
776 | it loads the perl code from the given file and executes it. This makes it |
779 | it loads the perl code from the given file and executes it. This makes it |
777 | easier to write more complicated or larger programs. |
780 | easier to write more complicated or larger programs. |
778 | |
781 | |
779 | =back |
782 | =back |
780 | |
783 | |
|
|
784 | |
781 | =head1 SEE ALSO |
785 | =head1 SEE ALSO |
782 | |
786 | |
783 | For ideas on what you can do, and some introductory material, try |
787 | For ideas on what you can do with BCD stores in |
|
|
788 | general, and some introductory material, try |
784 | L<http://www.mistyprojects.co.uk/documents/BCDEdit/index.html>. |
789 | L<http://www.mistyprojects.co.uk/documents/BCDEdit/index.html>. |
785 | |
790 | |
786 | For good reference on BCD objects and elements, see Geoff Chappels pages |
791 | For good reference on which BCD objects and |
|
|
792 | elements exist, see Geoff Chappell's pages at |
787 | at L<http://www.geoffchappell.com/notes/windows/boot/bcd/index.htm>. |
793 | L<http://www.geoffchappell.com/notes/windows/boot/bcd/index.htm>. |
788 | |
794 | |
789 | =head1 AUTHOR |
795 | =head1 AUTHOR |
790 | |
796 | |
791 | Written by Marc A. Lehmann <pbcdedit@schmorp.de>. |
797 | Written by Marc A. Lehmann L<pbcdedit@schmorp.de>. |
792 | |
798 | |
793 | =head1 REPORTING BUGS |
799 | =head1 REPORTING BUGS |
794 | |
800 | |
795 | Bugs can be reported dorectly tt he author at L<pcbedit@schmorp.de>. |
801 | Bugs can be reported directly the author at L<pcbedit@schmorp.de>. |
796 | |
802 | |
797 | =head1 BUGS AND SHORTCOMINGS |
803 | =head1 BUGS AND SHORTCOMINGS |
798 | |
804 | |
799 | This should be a module. Of a series of modules, even. |
805 | This should be a module. Of a series of modules, even. |
800 | |
806 | |
801 | Registry code should preserve classname and security descriptor data, and |
807 | Registry code should preserve classname and security descriptor data, and |
802 | whatever else is necessary to read and write any registry hive file. |
808 | whatever else is necessary to read and write any registry hive file. |
803 | |
809 | |
804 | I am also not happy with device descriptors being strings rather than a |
810 | I am also not happy with device descriptors being strings rather than a |
805 | data structure, but strings are probably better for command line usage. In |
811 | data structure, but strings are probably better for command line usage. In |
806 | any case,. device descriptors could be converted by simply "splitting" at |
812 | any case, device descriptors could be converted by simply "splitting" at |
807 | "=" and "," into an array reference, recursively. |
813 | "=" and "," into an array reference, recursively. |
808 | |
814 | |
809 | =head1 HOMEPAGE |
815 | =head1 HOMEPAGE |
810 | |
816 | |
811 | Original versions of this program can be found at |
817 | Original versions of this program can be found at |
… | |
… | |
818 | free to change and redistribute it. There is NO WARRANTY, to the extent |
824 | free to change and redistribute it. There is NO WARRANTY, to the extent |
819 | permitted by law. |
825 | permitted by law. |
820 | |
826 | |
821 | =cut |
827 | =cut |
822 | |
828 | |
823 | BEGIN { require "common/sense.pm"; common::sense->import } # common sense is optional, but recommended |
829 | # common sense is optional, but recommended |
|
|
830 | BEGIN { eval { require "common/sense.pm"; } && common::sense->import } |
824 | |
831 | |
825 | use Data::Dump; |
|
|
826 | use Encode (); |
832 | use Encode (); |
827 | use List::Util (); |
833 | use List::Util (); |
828 | use IO::Handle (); |
834 | use IO::Handle (); |
829 | use Time::HiRes (); |
835 | use Time::HiRes (); |
830 | |
836 | |
… | |
… | |
853 | or die "$path: short read\n"; |
859 | or die "$path: short read\n"; |
854 | |
860 | |
855 | $buf |
861 | $buf |
856 | } |
862 | } |
857 | |
863 | |
858 | # sources and resources used for this: |
864 | # sources and resources used for writing pbcdedit |
|
|
865 | # |
859 | # registry: |
866 | # registry: |
860 | # https://github.com/msuhanov/regf/blob/master/Windows%20registry%20file%20format%20specification.md |
867 | # https://github.com/msuhanov/regf/blob/master/Windows%20registry%20file%20format%20specification.md |
861 | # http://amnesia.gtisc.gatech.edu/~moyix/suzibandit.ltd.uk/MSc/ |
868 | # http://amnesia.gtisc.gatech.edu/~moyix/suzibandit.ltd.uk/MSc/ |
862 | # bcd: |
869 | # bcd: |
863 | # http://www.geoffchappell.com/notes/windows/boot/bcd/index.htm |
870 | # http://www.geoffchappell.com/notes/windows/boot/bcd/index.htm |
… | |
… | |
2242 | Objects => [undef, \%objects], |
2249 | Objects => [undef, \%objects], |
2243 | }]] |
2250 | }]] |
2244 | } |
2251 | } |
2245 | |
2252 | |
2246 | ############################################################################# |
2253 | ############################################################################# |
|
|
2254 | # edit instructions |
2247 | |
2255 | |
2248 | sub bcd_edit_eval { |
2256 | sub bcd_edit_eval { |
2249 | package pbcdedit; |
2257 | package pbcdedit; |
2250 | |
2258 | |
2251 | our ($PATH, $BCD, $DEFAULT); |
2259 | our ($PATH, $BCD, $DEFAULT); |
… | |
… | |
2269 | |
2277 | |
2270 | if ($insn eq "get") { |
2278 | if ($insn eq "get") { |
2271 | my $object = shift @insns; |
2279 | my $object = shift @insns; |
2272 | my $elem = shift @insns; |
2280 | my $elem = shift @insns; |
2273 | |
2281 | |
2274 | $object = $default if $object eq "{default}"; |
2282 | $object = $object eq "{default}" ? $default : dec_wguid enc_wguid $object; |
2275 | |
2283 | |
2276 | print $bcd->{$object}{$elem}, "\n"; |
2284 | print $bcd->{$object}{$elem}, "\n"; |
2277 | |
2285 | |
2278 | } elsif ($insn eq "set") { |
2286 | } elsif ($insn eq "set") { |
2279 | my $object = shift @insns; |
2287 | my $object = shift @insns; |
2280 | my $elem = shift @insns; |
2288 | my $elem = shift @insns; |
2281 | my $value = shift @insns; |
2289 | my $value = shift @insns; |
2282 | |
2290 | |
2283 | $object = $default if $object eq "{default}"; |
2291 | $object = $object eq "{default}" ? $default : dec_wguid enc_wguid $object; |
2284 | |
2292 | |
2285 | $bcd->{$object}{$elem} = $value; |
2293 | $bcd->{$object}{$elem} = $value; |
2286 | |
2294 | |
2287 | } elsif ($insn eq "eval") { |
2295 | } elsif ($insn eq "eval") { |
2288 | bcd_edit_eval shift @insns; |
2296 | bcd_edit_eval shift @insns; |
… | |
… | |
2298 | } |
2306 | } |
2299 | |
2307 | |
2300 | } |
2308 | } |
2301 | |
2309 | |
2302 | ############################################################################# |
2310 | ############################################################################# |
|
|
2311 | # command line parser |
2303 | |
2312 | |
2304 | # json to stdout |
2313 | # json to stdout |
2305 | sub prjson($) { |
2314 | sub prjson($) { |
2306 | print $json_coder->encode ($_[0]); |
2315 | print $json_coder->encode ($_[0]); |
2307 | } |
2316 | } |