… | |
… | |
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.3'; |
25 | our $JSON_VERSION = 1; # the versiobn of the json objects generated by this program |
25 | our $JSON_VERSION = 3; # the version of the json objects generated by this program |
|
|
26 | |
|
|
27 | our $CHANGELOG = <<EOF; |
|
|
28 | |
|
|
29 | - editorial fixes to the documentation. |
|
|
30 | |
|
|
31 | 1.3 Sat Aug 17 07:04:15 CEST 2019 |
|
|
32 | - output of pbcdedit elements --json has changed, as it didn't |
|
|
33 | take the reorganisation by classes fully into account. |
|
|
34 | - json schema bumped to 3. |
|
|
35 | - new "bcd-device" and "bcd-legacy-device" subcommands. |
|
|
36 | - implement --json option for lsblk. |
|
|
37 | |
|
|
38 | 1.2 Fri Aug 16 00:20:41 CEST 2019 |
|
|
39 | - bcd element names now depend on the bcd object type they are in, |
|
|
40 | also affects "elements" output. |
|
|
41 | - json schema bumped to 2. |
|
|
42 | - new version command. |
|
|
43 | - numerous minor bugfixes. |
|
|
44 | |
|
|
45 | EOF |
26 | |
46 | |
27 | =head1 NAME |
47 | =head1 NAME |
28 | |
48 | |
29 | pbcdedit - portable boot configuration data (BCD) store editor |
49 | pbcdedit - portable boot configuration data (BCD) store editor |
30 | |
50 | |
31 | =head1 SYNOPSIS |
51 | =head1 SYNOPSIS |
32 | |
52 | |
33 | pbcdedit help # output manual page |
53 | pbcdedit help # output manual page |
|
|
54 | pbcdedit version # output version and changelog |
|
|
55 | |
34 | pbcdedit export path/to/BCD # output BCD hive as JSON |
56 | pbcdedit export path/to/BCD # output BCD hive as JSON |
35 | pbcdedit import path/to/bcd # convert standard input to BCD hive |
57 | pbcdedit import path/to/BCD # convert standard input to BCD hive |
36 | pbcdedit edit path/to/BCD edit-instructions... |
58 | pbcdedit edit path/to/BCD edit-instructions... |
37 | |
59 | |
38 | pbcdedit objects # list all supported object aliases and types |
60 | pbcdedit objects # list all supported object aliases and types |
39 | pbcdedit elements # list all supported bcd element aliases |
61 | pbcdedit elements # list all supported bcd element aliases |
40 | |
62 | |
|
|
63 | # Example: enable text-based boot menu. |
|
|
64 | pbcdedit edit /my/BCD set '{default}' bootmenupolicy 1 |
|
|
65 | |
|
|
66 | # Example change system device to first partition containing winload. |
|
|
67 | pbcdedit edit /my/BCD \ |
|
|
68 | set '{default}' device 'locate=<null>,element,path' \ |
|
|
69 | set '{default}' osdevice 'locate=<null>,element,path' |
|
|
70 | |
|
|
71 | |
41 | =head1 DESCRIPTION |
72 | =head1 DESCRIPTION |
42 | |
73 | |
43 | This program allows you to create, read and modify Boot Configuration Data |
74 | This program allows you to create, read and modify Boot Configuration Data |
44 | (BCD) stores used by Windows Vista and newer versions of Windows. |
75 | (BCD) stores used by Windows Vista and newer versions of Windows. |
45 | |
76 | |
… | |
… | |
58 | |
89 | |
59 | =item Does not rely on Windows |
90 | =item Does not rely on Windows |
60 | |
91 | |
61 | As the "portable" in the name implies, this program does not rely on |
92 | 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 |
93 | C<bcdedit> or other windows programs or libraries, it works on any system |
63 | that supports at least perl version 5.14. |
94 | that supports at least perl version 5.16. |
64 | |
95 | |
65 | =item Decodes and encodes BCD device elements |
96 | =item Decodes and encodes BCD device elements |
66 | |
97 | |
67 | PBCDEDIT can concisely decode and encode BCD device element contents. This |
98 | 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 |
99 | is pretty unique, and offers a lot of potential that can't be realised |
… | |
… | |
75 | sensitive data. |
106 | sensitive data. |
76 | |
107 | |
77 | =back |
108 | =back |
78 | |
109 | |
79 | The target audience for this program is professionals and tinkerers who |
110 | 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 |
111 | 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 |
112 | program to use and requires patience and a good understanding of BCD |
82 | stores. |
113 | stores. |
83 | |
114 | |
84 | |
115 | |
85 | =head1 SUBCOMMANDS |
116 | =head1 SUBCOMMANDS |
86 | |
117 | |
87 | PCBEDIT expects a subcommand as first argument that tells it what to |
118 | PBCDEDIT expects a subcommand as first argument that tells it what to |
88 | do. The following subcommands exist: |
119 | do. The following subcommands exist: |
89 | |
120 | |
90 | =over |
121 | =over |
91 | |
122 | |
92 | =item help |
123 | =item C<help> |
93 | |
124 | |
94 | Displays the whole manuale page (this document). |
125 | Displays the whole manual page (this document). |
95 | |
126 | |
|
|
127 | =item C<version> |
|
|
128 | |
|
|
129 | This outputs the PBCDEDIT version, the JSON schema version it uses and the |
|
|
130 | full log of changes. |
|
|
131 | |
96 | =item export F<path> |
132 | =item C<export> F<path> |
97 | |
133 | |
98 | Reads a BCD data store and writes a JSON representation of it to standard |
134 | Reads a BCD data store and writes a JSON representation of it to standard |
99 | output. |
135 | output. |
100 | |
136 | |
101 | The format of the data is explained later in this document. |
137 | The format of the data is explained later in this document. |
102 | |
138 | |
103 | Example: read a BCD store, modify it wiht an extenral program, write it again. |
139 | Example: read a BCD store, modify it with an external program, write it |
|
|
140 | again. |
104 | |
141 | |
105 | pbcdedit export BCD | modify-json-somehow | pbcdedit import BCD |
142 | pbcdedit export BCD | modify-json-somehow | pbcdedit import BCD |
106 | |
143 | |
107 | =item import F<path> |
144 | =item C<import> F<path> |
108 | |
145 | |
109 | The reverse of C<export>: Reads a JSON representation of a BCD data store |
146 | 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. |
147 | from standard input, and creates or replaces the given BCD data store. |
111 | |
148 | |
112 | =item edit F<path> instructions... |
149 | =item C<edit> F<path> I<instructions...> |
113 | |
150 | |
114 | Load a BCD data store, apply some instructions to it, and save it again. |
151 | Load a BCD data store, apply some instructions to it, and save it again. |
115 | |
152 | |
116 | See the section L<EDITING BCD DATA STORES>, below, for more info. |
153 | See the section L<EDITING BCD STORES>, below, for more info. |
117 | |
154 | |
118 | =item parse F<path> instructions... |
155 | =item C<parse> F<path> I<instructions...> |
119 | |
156 | |
120 | Same as C<edit>, above, except it doesn't save the data store again. Can |
157 | Same as C<edit>, above, except it doesn't save the data store again. Can |
121 | be useful to extract some data from it. |
158 | be useful to extract some data from it. |
122 | |
159 | |
123 | =item lsblk |
160 | =item C<lsblk> [C<--json>] |
124 | |
161 | |
125 | On a GNU/Linux system, you can get a list of partition device descriptors |
162 | 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 |
163 | using this command - the external C<lsblk> command is required, as well as |
127 | a mounted C</sys> file system. |
164 | a mounted C</sys> file system. |
128 | |
165 | |
129 | The output will be a list of all partitions in the system and C<partition> |
166 | 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> |
167 | descriptors for GPT and both C<legacypartition> and C<partition> |
131 | descritpors for MBR partitions. |
168 | descriptors for MBR partitions. |
132 | |
169 | |
|
|
170 | With C<--json> it will print similar information as C<lsblk --json>, but |
|
|
171 | with extra C<bcd_device> and C<bcd_legacy_device> attributes. |
|
|
172 | |
|
|
173 | =item C<bcd-device> F<path> |
|
|
174 | |
|
|
175 | Tries to find the BCD device element for the given device, which currently |
|
|
176 | must be a a partition of some kind. Prints the C<partition=> descriptor as |
|
|
177 | a result, or nothing. Exit status will be true on success, and false on |
|
|
178 | failure. |
|
|
179 | |
|
|
180 | Like C<lsblk>, above, this likely only works on GNU/Linux systems. |
|
|
181 | |
|
|
182 | Example: print the partition descriptor of tghe partition with label DATA. |
|
|
183 | |
|
|
184 | $ pbcdedit bcd-device /dev/disk/by-label/DATA |
|
|
185 | partition=<null>,harddisk,mbr,47cbc08a,213579202560 |
|
|
186 | |
|
|
187 | =item C<bcd-legacy-device> F<path> |
|
|
188 | |
|
|
189 | Like above, but uses a C<legacypartition> descriptor instead. |
|
|
190 | |
133 | =item objects [--json] |
191 | =item C<objects> [C<--json>] |
134 | |
192 | |
135 | Outputs two tables: a table listing all type aliases with their hex bcd |
193 | 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 |
194 | element ID, and all object name aliases with their GUID and default type |
137 | (if any). |
195 | (if any). |
138 | |
196 | |
139 | With C<--json> it prints similar information as a JSON object, for easier parsing. |
197 | With C<--json> it prints similar information as a JSON object, for easier parsing. |
140 | |
198 | |
141 | =item elements [--json] |
199 | =item C<elements> [C<--json>] |
142 | |
200 | |
143 | Outputs a table of known element aliases with their hex ID and the format |
201 | Outputs a table of known element aliases with their hex ID and the format |
144 | type. |
202 | type. |
145 | |
203 | |
146 | With C<--json> it prints similar information as a JSON object, for easier parsing. |
204 | With C<--json> it prints similar information as a JSON object, for easier parsing. |
147 | |
205 | |
148 | =item export-regf F<path> |
206 | =item C<export-regf> F<path> |
149 | |
207 | |
150 | This has nothing to do with BCD data stores - it takes a registry hive |
208 | This has nothing to do with BCD stores, but simply exposes PCBEDIT's |
|
|
209 | 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 |
210 | and outputs a JSON representation of it to standard output. |
152 | output. |
|
|
153 | |
211 | |
154 | Hive versions 1.2 till 1.6 are supported. |
212 | Hive versions 1.2 till 1.6 are supported. |
155 | |
213 | |
156 | =item import-regf F<path> |
214 | =item C<import-regf> F<path> |
157 | |
215 | |
158 | The reverse of C<export-regf>: reads a JSON representation of a registry |
216 | 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 |
217 | hive from standard input and creates or replaces the registry hive file |
160 | argument. |
218 | given as argument. |
161 | |
219 | |
162 | The written hive will always be in a slightly modified version 1.3 |
220 | 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 |
221 | format. It's not the format windows would generate, but it should be |
164 | understood by any conformant hive reader. |
222 | understood by any conformant hive reader. |
165 | |
223 | |
166 | Note that the representation chosen by PBCDEDIT currently throws away |
224 | Note that the representation chosen by PBCDEDIT currently throws away |
167 | clasname data (often used for feeble attemtps at hiding stuff by |
225 | classname data (often used for feeble attempts at hiding stuff by |
168 | Microsoft) and security descriptors, so if you write anything other than |
226 | Microsoft) and security descriptors, so if you write anything other than |
169 | a BCD hive you will most likely destroy it. |
227 | a BCD hive you will most likely destroy it. |
170 | |
228 | |
171 | =back |
229 | =back |
172 | |
230 | |
173 | |
231 | |
174 | =head1 BCD DATA STORE REPRESENTATION FORMAT |
232 | =head1 BCD STORE REPRESENTATION FORMAT |
175 | |
233 | |
176 | A BCD data store is represented as a JSON object with one special key, |
234 | 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 |
235 | 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> |
236 | one key-value pair in the object, and an additional key called C<meta> |
179 | contains meta information. |
237 | contains meta information. |
… | |
… | |
215 | } |
273 | } |
216 | |
274 | |
217 | =head2 Minimal BCD to boot windows |
275 | =head2 Minimal BCD to boot windows |
218 | |
276 | |
219 | Experimentally I found the following BCD is the minimum required to |
277 | Experimentally I found the following BCD is the minimum required to |
220 | successfully boot any post-XP version of Windows (suitable C<device> and |
278 | successfully boot any post-XP version of Windows (assuming suitable |
221 | C<osdevice> values, of course): |
279 | C<device> and C<osdevice> values, of course, and assuming a BIOS boot - |
|
|
280 | for UEFI, you should use F<winload.efi> instead of F<winload.exe>): |
222 | |
281 | |
223 | { |
282 | { |
224 | "{bootmgr}" : { |
283 | "{bootmgr}" : { |
225 | "resumeobject" : "{45b547a7-8ca6-4417-9eb0-a257b61f35b4}" |
284 | "default" : "{45b547a7-8ca6-4417-9eb0-a257b61f35b4}" |
226 | }, |
285 | }, |
227 | |
286 | |
228 | "{45b547a7-8ca6-4417-9eb0-a257b61f35b1}" : { |
287 | "{45b547a7-8ca6-4417-9eb0-a257b61f35b1}" : { |
229 | "type" : "application::osloader", |
288 | "type" : "application::osloader", |
230 | "description" : "Windows Boot", |
289 | "description" : "Windows Boot", |
… | |
… | |
242 | =head2 The C<meta> key |
301 | =head2 The C<meta> key |
243 | |
302 | |
244 | The C<meta> key is not stored in the BCD data store but is used only |
303 | 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 |
304 | 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 |
305 | 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 |
306 | the JSON schema version of PBCDEDIT. This ensures that different and |
248 | incompatible versions of PBCDEDIT will not read and misinterΓΌret each |
307 | incompatible versions of PBCDEDIT will not read and misinterpret each |
249 | others data. |
308 | others data. |
250 | |
309 | |
251 | =head2 The object keys |
310 | =head2 The object keys |
252 | |
311 | |
253 | Every other key is a BCD object. There is usually a BCD object for the |
312 | 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 |
313 | boot manager, one for every boot option and a few others that store common |
255 | settings inherited by these. |
314 | settings inherited by these. |
256 | |
315 | |
257 | Each BCD object is represented by a GUID wrapped in curly braces. These |
316 | 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 |
317 | 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. |
318 | other. When adding a new boot option, you can simply generate a new GUID. |
260 | |
319 | |
261 | Some of these GUIDs are fixed well known GUIDs which PBCDEDIT will decode |
320 | 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 |
321 | into human-readable strings such as C<{globalsettings}>, which is the same |
263 | as C<{7ea2e1ac-2e61-4728-aaa3-896d9d0a9f0e}>. |
322 | as C<{7ea2e1ac-2e61-4728-aaa3-896d9d0a9f0e}>. |
… | |
… | |
297 | get a list of all BCD elements known to PBCDEDIT by running F<pbcdedit |
356 | get a list of all BCD elements known to PBCDEDIT by running F<pbcdedit |
298 | elements>. |
357 | elements>. |
299 | |
358 | |
300 | What was said about duplicate keys mapping to the same object is true for |
359 | 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, |
360 | elements as well, so, again, you should always use the canonical name, |
302 | whcih is the human radable alias, if known. |
361 | which is the human readable alias, if known. |
303 | |
362 | |
304 | =head3 BCD element types |
363 | =head3 BCD element types |
305 | |
364 | |
306 | Each BCD element has a type such as I<string> or I<boolean>. This type |
365 | 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 |
366 | determines how the value is interpreted, and most of them are pretty easy |
… | |
… | |
319 | "description" : "Windows 10", |
378 | "description" : "Windows 10", |
320 | "systemroot" : "\\Windows", |
379 | "systemroot" : "\\Windows", |
321 | |
380 | |
322 | =item boolean |
381 | =item boolean |
323 | |
382 | |
324 | Almost as simnple are booleans, which represent I<true>/I<false>, |
383 | 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 |
384 | 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 |
385 | 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 |
386 | values will be accepted, but PBCDEDIT doesn't guarantee how these are |
328 | interpreted. |
387 | interpreted. |
329 | |
388 | |
… | |
… | |
333 | |
392 | |
334 | "displaybootmenu" : 0, |
393 | "displaybootmenu" : 0, |
335 | |
394 | |
336 | =item integer |
395 | =item integer |
337 | |
396 | |
338 | Again, very simple, this is a 64 bit integer. IT can be either specified |
397 | 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 |
398 | as a decimal number, as a hex number (by prefixing it with C<0x>) or as a |
340 | binatry number (prefix C<0b>). |
399 | binary number (prefix C<0b>). |
341 | |
400 | |
342 | For example, the boot C<timeout> is an integer, specifying the automatic |
401 | For example, the boot C<timeout> is an integer, specifying the automatic |
343 | boot delay in seconds: |
402 | boot delay in seconds: |
344 | |
403 | |
345 | "timeout" : 30, |
404 | "timeout" : 30, |
346 | |
405 | |
347 | =item integer list |
406 | =item integer list |
348 | |
407 | |
349 | This is a list of 64 bit integers separated by whitespace. It is not used |
408 | 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 |
409 | much, so here is a somewhat artificial and untested example of using |
351 | C<customactions> to specify a certain custom, eh, action to be executed |
410 | C<customactions> to specify a certain custom, eh, action to be executed |
352 | when pressing C<F10> at boot: |
411 | when pressing C<F10> at boot: |
353 | |
412 | |
354 | "customactions" : "0x1000044000001 0x54000001", |
413 | "customactions" : "0x1000044000001 0x54000001", |
355 | |
414 | |
356 | =item guid |
415 | =item guid |
357 | |
416 | |
358 | This represents a single GUID value wrqapped in curly braces. It is used a |
417 | 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. |
418 | lot to refer from one BCD object to other one. |
360 | |
419 | |
361 | For example, The C<{bootmgr}> object might refer to a resume boot option |
420 | For example, The C<{bootmgr}> object might refer to a resume boot option |
362 | using C<resumeobject>: |
421 | using C<default>: |
363 | |
422 | |
364 | "resumeobject" : "{7ae02178-821d-11e7-8813-1c872c5f5ab0}", |
423 | "default" : "{7ae02178-821d-11e7-8813-1c872c5f5ab0}", |
365 | |
424 | |
366 | Human readable aliases are used and allowed. |
425 | Human readable aliases are used and allowed. |
367 | |
426 | |
368 | =item guid list |
427 | =item guid list |
369 | |
428 | |
370 | Similar to te guid type, this represents a list of such GUIDs, separated |
429 | Similar to the GUID type, this represents a list of such GUIDs, separated |
371 | by whitespace from each other. |
430 | by whitespace from each other. |
372 | |
431 | |
373 | For example, many BCD objects can I<inherit> elements from other BCD |
432 | 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 |
433 | objects by specifying the GUIDs of those other objects in a GUID list |
375 | called surprisingly called C<inherit>: |
434 | called surprisingly called C<inherit>: |
376 | |
435 | |
377 | "inherit" : "{dbgsettings} {emssettings} {badmemory}", |
436 | "inherit" : "{dbgsettings} {emssettings} {badmemory}", |
378 | |
437 | |
379 | This example also shows how human readable aliases can be used. |
438 | This example also shows how human readable aliases can be used. |
… | |
… | |
383 | This type is why I write I<most> are easy to explain earlier: This type |
442 | This type is why I write I<most> are easy to explain earlier: This type |
384 | is the pinnacle of Microsoft-typical hacks layered on top of other |
443 | is the pinnacle of Microsoft-typical hacks layered on top of other |
385 | hacks. Understanding this type took more time than writing all the rest of |
444 | hacks. Understanding this type took more time than writing all the rest of |
386 | PBCDEDIT, and because it is so complex, this type has its own subsection |
445 | PBCDEDIT, and because it is so complex, this type has its own subsection |
387 | below. |
446 | below. |
|
|
447 | |
388 | =back |
448 | =back |
389 | |
449 | |
390 | =head4 The BCD "device" element type |
450 | =head3 The BCD "device" element type |
391 | |
451 | |
392 | Device elements specify, well, devices. They are used for such diverse |
452 | 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 |
453 | 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, |
454 | devices, but most commonly they are used to specify the disk (harddisk, |
395 | cdrom ramdisk, vhd...) to boot from. |
455 | cdrom, ramdisk, vhd...) to boot from. |
396 | |
456 | |
397 | The device element is kind of a mini-language in its own which is much |
457 | 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 - |
458 | more versatile then the limited windows interface to it - BCDEDIT - |
399 | reveals. |
459 | reveals. |
400 | |
460 | |
… | |
… | |
403 | element, so almost everything known about it had to be researched first |
463 | 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 |
464 | in the process of writing this script, and consequently, support for BCD |
405 | device elements is partial only. |
465 | device elements is partial only. |
406 | |
466 | |
407 | On the other hand, the expressive power of PBCDEDIT in specifying devices |
467 | 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 |
468 | is much greater than BCDEDIT and therefore more can be done with it. The |
409 | downside is that BCD device elements are much more complicated than what |
469 | downside is that BCD device elements are much more complicated than what |
410 | you might think from reading the BCDEDIT documentation. |
470 | you might think from reading the BCDEDIT documentation. |
411 | |
471 | |
412 | In other words, simple things are complicated, and complicated things are |
472 | In other words, simple things are complicated, and complicated things are |
413 | possible. |
473 | possible. |
414 | |
474 | |
415 | Anyway, the general syntax of device elements is an optional GUID, |
475 | Anyway, the general syntax of device elements is an optional GUID, |
416 | followed by a device type, optionally followed by hexdecimal flags in |
476 | followed by a device type, optionally followed by hexadecimal flags in |
417 | angle brackets, optionally followed by C<=> and a comma-separated list of |
477 | 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. |
478 | arguments, some of which can be (and often are) in turn devices again. |
419 | |
479 | |
420 | [{GUID}]type[<flags>][=arg,arg...] |
480 | [{GUID}]type[<flags>][=arg,arg...] |
421 | |
481 | |
… | |
… | |
447 | The types understood and used by PBCDEDIT are as follows (keep in mind |
507 | 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): |
508 | that not of all the following is necessarily supported in PBCDEDIT): |
449 | |
509 | |
450 | =over |
510 | =over |
451 | |
511 | |
452 | =item binary=hex... |
512 | =item C<binary=>I<hex...> |
453 | |
513 | |
454 | This type isn't actually a real BCD element type, but a fallback for those |
514 | 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 |
515 | 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 |
516 | 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. |
517 | convert the device into this type with a hexdump of the element data. |
458 | |
518 | |
459 | =item null |
519 | =item C<null> |
460 | |
520 | |
461 | This is another special type - sometimes, a device all zero-filled, which |
521 | This is another special type - sometimes, a device is all zero-filled, |
462 | is not valid. This can mark the absence of a device or something PBCDEDIT |
522 | which is not valid. This can mark the absence of a device or something |
463 | does not understand, so it decodes it into this special "all zero" type |
523 | PBCDEDIT does not understand, so it decodes it into this special "all |
464 | called C<null>. |
524 | zero" type called C<null>. |
465 | |
525 | |
466 | It's most commonly found in devices that can use an optional parent |
526 | It's most commonly found in devices that can use an optional parent |
467 | device, when no parent device is used. |
527 | device, when no parent device is used. |
468 | |
528 | |
469 | =item boot |
529 | =item C<boot> |
470 | |
530 | |
471 | Another type without parameters, this refers to the device that was booted |
531 | Another type without parameters, this refers to the device that was booted |
472 | from (nowadays typically the EFI system partition). |
532 | from (nowadays typically the EFI system partition). |
473 | |
533 | |
474 | =item vmbus=interfacetype,interfaceinstance |
534 | =item C<vmbus=>I<interfacetype>,I<interfaceinstance> |
475 | |
535 | |
476 | This specifies a VMBUS device with the given interface type and interface |
536 | This specifies a VMBUS device with the given interface type and interface |
477 | instance, both of which are "naked" (no curly braces) GUIDs. |
537 | instance, both of which are "naked" (no curly braces) GUIDs. |
478 | |
538 | |
479 | Made-up example (couldn't find a single example on the web): |
539 | Made-up example (couldn't find a single example on the web): |
480 | |
540 | |
481 | vmbus=c376c1c3-d276-48d2-90a9-c04748072c60,12345678-a234-b234-c234-d2345678abcd |
541 | vmbus=c376c1c3-d276-48d2-90a9-c04748072c60,12345678-a234-b234-c234-d2345678abcd |
482 | |
542 | |
483 | =item partition=<parent>,devicetype,partitiontype,diskid,partitionid |
543 | =item C<partition=><I<parent>>,I<devicetype>,I<partitiontype>,I<diskid>,I<partitionid> |
484 | |
544 | |
485 | This designates a specific partition on a block device. C<< <parent> |
545 | 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 |
546 | 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. |
547 | that the angle brackets around I<parent> are part of the syntax. |
488 | |
548 | |
489 | C<devicetypes> is one of C<harddisk>, C<floppy>, C<cdrom>, C<ramdisk>, |
549 | 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, |
550 | 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 |
551 | 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. |
552 | and C<vhd> is used to treat files as virtual harddisks, i.e. F<vhd> and |
|
|
553 | F<vhdx> files. |
493 | |
554 | |
494 | The C<partitiontype> is either C<mbr>, C<gpt> or C<raw>, the latter being |
555 | 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" |
556 | used for devices without partitions, such as cdroms, where the "partition" |
496 | is usually the whole device. |
557 | is usually the whole device. |
497 | |
558 | |
498 | The C<diskid> identifies the disk or device using a unique signature, and |
559 | 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 |
560 | the same is true for the I<partitionid>. How these are interpreted depends |
500 | on the C<partitiontype>: |
561 | on the I<partitiontype>: |
501 | |
562 | |
502 | =over |
563 | =over |
503 | |
564 | |
504 | =item mbr |
565 | =item C<mbr> |
505 | |
566 | |
506 | The C<diskid> is the 32 bit disk signature stored at offset 0x1b8 in the |
567 | 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 |
568 | 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>. |
569 | hex number. That is, the bytes C<01 02 03 04> would become C<04030201>. |
509 | |
570 | |
510 | Diskpart (using the C<DETAIL> command) and the C<lsblk> comamnd typically |
571 | 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 |
572 | found on GNU/Linux systems (using e.g. C<lsblk -o NAME,PARTUUID>) can |
512 | display the disk id. |
573 | display the I<diskid>. |
513 | |
574 | |
514 | The C<partitionid> is the byte offset(!) of the partition counting from |
575 | The I<partitionid> is the byte offset(!) of the partition counting from |
515 | the beginning of the MBR. |
576 | the beginning of the MBR. |
516 | |
577 | |
517 | Example, use the partition on the harddisk with C<diskid> C<47cbc08a> |
578 | Example, use the partition on the harddisk with I<diskid> C<47cbc08a> |
518 | starting at sector C<2048> (= 1048576 / 512). |
579 | starting at sector C<2048> (= 1048576 / 512). |
519 | |
580 | |
520 | partition=<null>,harddisk,mbr,47cbc08a,1048576 |
581 | partition=<null>,harddisk,mbr,47cbc08a,1048576 |
521 | |
582 | |
522 | =item gpt |
583 | =item C<gpt> |
523 | |
584 | |
524 | The C<diskid> is the disk UUID/disk identifier GUID from the partition |
585 | 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 |
586 | 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). |
587 | partition unique GUID (displayed using e.g. the F<gdisk> F<i> command). |
527 | |
588 | |
528 | Example: use the partition C<76d39e5f-ad1b-407e-9c05-c81eb83b57dd> on GPT |
589 | Example: use the partition C<76d39e5f-ad1b-407e-9c05-c81eb83b57dd> on GPT |
529 | disk C<9742e468-9206-48a0-b4e4-c4e9745a356a>. |
590 | disk C<9742e468-9206-48a0-b4e4-c4e9745a356a>. |
530 | |
591 | |
531 | partition=<null>,harddisk,gpt,9742e468-9206-48a0-b4e4-c4e9745a356a,76d39e5f-ad1b-407e-9c05-c81eb83b57dd |
592 | partition=<null>,harddisk,gpt,9742e468-9206-48a0-b4e4-c4e9745a356a,76d39e5f-ad1b-407e-9c05-c81eb83b57dd |
532 | |
593 | |
533 | =item raw |
594 | =item C<raw> |
534 | |
595 | |
535 | Instead of diskid and partitionid, this type only accepts a decimal disk |
596 | 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 |
597 | disk number and signifies the whole disk. BCDEDIT cannot display the |
537 | device, and I am doubtful whether it has a useful effect. |
598 | resulting device, and I am doubtful whether it has a useful effect. |
538 | |
599 | |
539 | =back |
600 | =back |
540 | |
601 | |
541 | =item legacypartition=<parent>,devicetype,partitiontype,diskid,partitionid |
602 | =item C<legacypartition=><I<parent>>,I<devicetype>,I<partitiontype>,I<diskid>,I<partitionid> |
542 | |
603 | |
543 | This is exactly the same as the C<partition> type, except for a tiny |
604 | 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 |
605 | detail: instead of using the partition start offset, this type uses the |
545 | partition number for MBR disks. Behaviour other partition types should be |
606 | partition number for MBR disks. Behaviour other partition types should be |
546 | the same. |
607 | the same. |
547 | |
608 | |
548 | The partition number starts at C<1> and skips unused partition, so if |
609 | 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 |
610 | 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 |
611 | 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 |
612 | partition inside the extended partition is number C<3>, regardless of any |
552 | gaps. |
613 | gaps. |
553 | |
614 | |
554 | =item locate=<parent>,locatetype,locatearg |
615 | =item C<locate=><I<parent>>,I<locatetype>,I<locatearg> |
555 | |
616 | |
556 | This device description will make the bootloader search for a partition |
617 | This device description will make the bootloader search for a partition |
557 | with a given path. |
618 | with a given path. |
558 | |
619 | |
559 | The C<< <parent> >> device is the device to search on (angle brackets are |
620 | 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 |
621 | still part of the syntax!) If it is C<null>, then C<locate> will |
561 | search all disks it can find. |
622 | search all disks it can find. |
562 | |
623 | |
563 | C<locatetype> is either C<element> or C<path>, and merely distinguishes |
624 | 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> |
625 | 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> |
626 | uses an element ID (either as hex or as name) as I<locatearg> and C<path> |
566 | uses a relative path as C<locatearg>. |
627 | uses a relative path as I<locatearg>. |
567 | |
628 | |
568 | Example: find any partition which has the C<magicfile.xxx> path in the |
629 | Example: find any partition which has the F<magicfile.xxx> path in the |
569 | root. |
630 | root. |
570 | |
631 | |
571 | locate=<null>,path,\magicfile.xxx |
632 | locate=<null>,path,\magicfile.xxx |
572 | |
633 | |
573 | Example: find any partition which has the path specified in the |
634 | Example: find any partition which has the path specified in the |
574 | C<systemroot> element (typically C<\Windows>). |
635 | C<systemroot> element (typically F<\Windows>). |
575 | |
636 | |
576 | locate=<null>,element,systemroot |
637 | locate=<null>,element,systemroot |
577 | |
638 | |
578 | =item block=devicetype,args... |
639 | =item C<block=>I<devicetype>,I<args...> |
579 | |
640 | |
580 | Last not least, the most complex type, C<block>, which... specifies block |
641 | Last not least, the most complex type, C<block>, which... specifies block |
581 | devices (which could be inside a F<vhdx> file for example). |
642 | devices (which could be inside a F<vhdx> file for example). |
582 | |
643 | |
583 | C<devicetypes> is one of C<harddisk>, C<floppy>, C<cdrom>, C<ramdisk>, |
644 | 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=>. |
645 | C<file> or C<vhd> - the same as for C<partition=>. |
585 | |
646 | |
586 | The remaining arguments change depending on the C<devicetype>: |
647 | The remaining arguments change depending on the I<devicetype>: |
587 | |
648 | |
588 | =over |
649 | =over |
589 | |
650 | |
590 | =item block=file,<parent>,path |
651 | =item C<block=file>,<I<parent>>,I<path> |
591 | |
652 | |
592 | Interprets the C<< <parent> >> device (typically a partition) as a |
653 | Interprets the I<parent> device (typically a partition) as a |
593 | filesystem and specifies a file path inside. |
654 | filesystem and specifies a file path inside. |
594 | |
655 | |
595 | =item block=vhd,<parent> |
656 | =item C<block=vhd>,<I<parent>> |
596 | |
657 | |
597 | Pretty much just changes the interpretation of C<< <parent> >>, which is |
658 | 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. |
659 | usually a disk image (C<block=file,...)>) to be a F<vhd> or F<vhdx> file. |
599 | |
660 | |
600 | =item block=ramdisk,<parent>,base,size,offset,path |
661 | =item C<block=ramdisk>,<I<parent>>,I<base>,I<size>,I<offset>,I<path> |
601 | |
662 | |
602 | Interprets the C<< <parent> >> device as RAM disk, using the (decimal) |
663 | Interprets the I<parent> device as RAM disk, using the (decimal) |
603 | base address, byte size and byte offset inside a file specified by |
664 | 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 |
665 | I<path>. The numbers are usually all C<0> because they can be extracted |
605 | from the RAM disk image or other parameters. |
666 | from the RAM disk image or other parameters. |
606 | |
667 | |
607 | This is most commonly used to boot C<wim> images. |
668 | This is most commonly used to boot C<wim> images. |
608 | |
669 | |
609 | =item block=floppy,drivenum |
670 | =item C<block=floppy>,I<drivenum> |
610 | |
671 | |
611 | Refers to a removable drive identified by a number. BCDEDIT cannot display |
672 | 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. |
673 | the resulting device, and it is not clear what effect it will have. |
613 | |
674 | |
614 | =item block=cdrom,drivenum |
675 | =item C<block=cdrom>,I<drivenum> |
615 | |
676 | |
616 | Pretty much the same as C<floppy> but for CD-ROMs. |
677 | Pretty much the same as C<floppy> but for CD-ROMs. |
617 | |
678 | |
618 | =item anything else |
679 | =item anything else |
619 | |
680 | |
620 | Probably not yet implemented. Tell me of your needs... |
681 | Probably not yet implemented. Tell me of your needs... |
621 | |
682 | |
622 | =back |
683 | =back |
623 | |
684 | |
624 | =back5 Examples |
685 | =head4 Examples |
625 | |
686 | |
626 | This concludes the syntax overview for device elements, but probably |
687 | 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 |
688 | leaves many questions open. I can't help with most of them, as I also have |
628 | many questions, but I can walk you through some actual examples using mroe |
689 | many questions, but I can walk you through some actual examples using more |
629 | complex aspects. |
690 | complex aspects. |
630 | |
691 | |
631 | =item locate=<block=vhd,<block=file,<locate=<null>,path,\disk.vhdx>,\disk.vhdx>>,element,path |
692 | =item C<< locate=<block=vhd,<block=file,<locate=<null>,path,\disk.vhdx>,\disk.vhdx>>,element,path >> |
632 | |
693 | |
633 | Just like with C declarations, you best treat device descriptors as |
694 | 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: |
695 | instructions to find your device and work your way from the inside out: |
635 | |
696 | |
636 | locate=<null>,path,\disk.vhdx |
697 | locate=<null>,path,\disk.vhdx |
… | |
… | |
643 | Next, this takes the device locate has found and finds a file called |
704 | 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 |
705 | 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 |
706 | only because we find the device using the same path as finding the disk |
646 | image, so this is purely incidental, although quite common. |
707 | image, so this is purely incidental, although quite common. |
647 | |
708 | |
648 | Bext, this file will be opened as a virtual disk: |
709 | Next, this file will be opened as a virtual disk: |
649 | |
710 | |
650 | block=vhd,<see above> |
711 | block=vhd,<see above> |
651 | |
712 | |
652 | And finally, inside this disk, another C<locate> will look for a partition |
713 | 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 |
714 | with a path as specified in the C<path> element, which most likely will be |
… | |
… | |
656 | locate=<see above>,element,path |
717 | locate=<see above>,element,path |
657 | |
718 | |
658 | As a result, this will boot the first Windows it finds on the first |
719 | As a result, this will boot the first Windows it finds on the first |
659 | F<disk.vhdx> disk image it can find anywhere. |
720 | F<disk.vhdx> disk image it can find anywhere. |
660 | |
721 | |
661 | =item locate=<block=vhd,<block=file,<partition=<null>,harddisk,mbr,47cbc08a,242643632128>,\win10.vhdx>>,element,path |
722 | =item C<< locate=<block=vhd,<block=file,<partition=<null>,harddisk,mbr,47cbc08a,242643632128>,\win10.vhdx>>,element,path >> |
662 | |
723 | |
663 | Pretty much the same as the previous case, but witzh a bit of variance. First, look for a specific partition on |
724 | Pretty much the same as the previous case, but with a bit of |
664 | an MBR-partitioned disk: |
725 | variance. First, look for a specific partition on an MBR-partitioned disk: |
665 | |
726 | |
666 | partition=<null>,harddisk,mbr,47cbc08a,242643632128 |
727 | partition=<null>,harddisk,mbr,47cbc08a,242643632128 |
667 | |
728 | |
668 | Then open the file F<\win10.vhdx> on that partition: |
729 | Then open the file F<\win10.vhdx> on that partition: |
669 | |
730 | |
… | |
… | |
675 | |
736 | |
676 | And again the windows loader (or whatever is in C<path>) will be searched: |
737 | And again the windows loader (or whatever is in C<path>) will be searched: |
677 | |
738 | |
678 | locate=<see above>,element,path |
739 | locate=<see above>,element,path |
679 | |
740 | |
680 | =item {b097d2b2-bc00-11e9-8a9a-525400123456}block<1>=ramdisk,<partition=<null>,harddisk,mbr,47cbc08a,242643632128>,0,0,0,\boot.wim |
741 | =item C<< {b097d2b2-bc00-11e9-8a9a-525400123456}block<1>=ramdisk,<partition=<null>,harddisk,mbr,47cbc08a,242643632128>,0,0,0,\boot.wim >> |
681 | |
742 | |
682 | This is quite different. First, it starts with a GUID. This GUID belongs |
743 | 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: |
744 | to a BCD object of type C<device>, which has additional parameters: |
684 | |
745 | |
685 | "{b097d2b2-bc00-11e9-8a9a-525400123456}" : { |
746 | "{b097d2b2-bc00-11e9-8a9a-525400123456}" : { |
… | |
… | |
688 | "ramdisksdidevice" : "partition=<null>,harddisk,mbr,47cbc08a,1048576", |
749 | "ramdisksdidevice" : "partition=<null>,harddisk,mbr,47cbc08a,1048576", |
689 | "ramdisksdipath" : "\boot.sdi" |
750 | "ramdisksdipath" : "\boot.sdi" |
690 | }, |
751 | }, |
691 | |
752 | |
692 | I will not go into many details, but this specifies a (presumably empty) |
753 | 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 |
754 | 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 |
755 | 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>. |
756 | see, this F<.sdi> file resides on a different C<partition>. |
696 | |
757 | |
697 | Continuitn, as always, form the inside out, first this device descriptor |
758 | Continuing, as always, from the inside out, first this device descriptor |
698 | finds a specific partition: |
759 | finds a specific partition: |
699 | |
760 | |
700 | partition=<null>,harddisk,mbr,47cbc08a,242643632128 |
761 | partition=<null>,harddisk,mbr,47cbc08a,242643632128 |
701 | |
762 | |
702 | And then specifies a C<ramdisk> image on this partition: |
763 | And then specifies a C<ramdisk> image on this partition: |
… | |
… | |
707 | seems to be always there on this kind of entry. |
768 | seems to be always there on this kind of entry. |
708 | |
769 | |
709 | If you have some good examples to add here, feel free to mail me. |
770 | If you have some good examples to add here, feel free to mail me. |
710 | |
771 | |
711 | |
772 | |
712 | =head1 EDITING BCD DATA STORES |
773 | =head1 EDITING BCD STORES |
713 | |
774 | |
714 | The C<edit> and C<parse> subcommands allow you to read a BCD data store |
775 | 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 |
776 | and modify it or extract data from it. This is done by executing a series |
716 | of "editing instructions" which are explained here. |
777 | of "editing instructions" which are explained here. |
717 | |
778 | |
718 | =over |
779 | =over |
719 | |
780 | |
720 | =item get I<object> I<element> |
781 | =item C<get> I<object> I<element> |
721 | |
782 | |
722 | Reads the BCD element I<element> from the BCD object I<object> and writes |
783 | 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 |
784 | 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 |
785 | or a human-readable alias, or the special string C<{default}>, which will |
725 | refer to the default BCD object. |
786 | refer to the default BCD object. |
726 | |
787 | |
727 | Example: find description of the default BCD object. |
788 | Example: find description of the default BCD object. |
728 | |
789 | |
729 | pbcdedit parse BCD get "{default}" description |
790 | pbcdedit parse BCD get "{default}" description |
730 | |
791 | |
731 | =item set I<object> I<element> I<value> |
792 | =item C<set> I<object> I<element> I<value> |
732 | |
793 | |
733 | Similar to C<get>, but sets the element to the given I<value> instead. |
794 | Similar to C<get>, but sets the element to the given I<value> instead. |
734 | |
795 | |
735 | Example: change bootmgr default too |
796 | Example: change the bootmgr default too |
736 | C<{b097d2ad-bc00-11e9-8a9a-525400123456}>: |
797 | C<{b097d2ad-bc00-11e9-8a9a-525400123456}>: |
737 | |
798 | |
738 | pbcdedit edit BCD set "{bootmgr}" resumeobject "{b097d2ad-bc00-11e9-8a9a-525400123456}" |
799 | pbcdedit edit BCD set "{bootmgr}" default "{b097d2ad-bc00-11e9-8a9a-525400123456}" |
739 | |
800 | |
740 | =item eval I<perlcode> |
801 | =item C<eval> I<perlcode> |
741 | |
802 | |
742 | This takes the next argument, interprets it as Perl code and |
803 | This takes the next argument, interprets it as Perl code and |
743 | evaluates it. This allows you to do more complicated modifications or |
804 | evaluates it. This allows you to do more complicated modifications or |
744 | extractions. |
805 | extractions. |
745 | |
806 | |
… | |
… | |
764 | The example given for C<get>, above, could be expressed like this with |
825 | The example given for C<get>, above, could be expressed like this with |
765 | C<eval>: |
826 | C<eval>: |
766 | |
827 | |
767 | pbcdedit edit BCD eval 'say $BCD->{$DEFAULT}{description}' |
828 | pbcdedit edit BCD eval 'say $BCD->{$DEFAULT}{description}' |
768 | |
829 | |
769 | The example given for C<set> could be expresed like this: |
830 | The example given for C<set> could be expressed like this: |
770 | |
831 | |
771 | pbcdedit edit BCD eval '$BCD->{$DEFAULT}{resumeobject} = "{b097d2ad-bc00-11e9-8a9a-525400123456}"' |
832 | pbcdedit edit BCD eval '$BCD->{"{bootmgr}"{default} = "{b097d2ad-bc00-11e9-8a9a-525400123456}"' |
772 | |
833 | |
773 | =item do I<path> |
834 | =item C<do> I<path> |
774 | |
835 | |
775 | Similar to C<eval>, above, but instead of using the argument as perl code, |
836 | 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 |
837 | it loads the perl code from the given file and executes it. This makes it |
777 | easier to write more complicated or larger programs. |
838 | easier to write more complicated or larger programs. |
778 | |
839 | |
779 | =back |
840 | =back |
780 | |
841 | |
|
|
842 | |
781 | =head1 SEE ALSO |
843 | =head1 SEE ALSO |
782 | |
844 | |
783 | For ideas on what you can do, and some introductory material, try |
845 | For ideas on what you can do with BCD stores in |
|
|
846 | general, and some introductory material, try |
784 | L<http://www.mistyprojects.co.uk/documents/BCDEdit/index.html>. |
847 | L<http://www.mistyprojects.co.uk/documents/BCDEdit/index.html>. |
785 | |
848 | |
786 | For good reference on BCD objects and elements, see Geoff Chappels pages |
849 | For good reference on which BCD objects and |
|
|
850 | elements exist, see Geoff Chappell's pages at |
787 | at L<http://www.geoffchappell.com/notes/windows/boot/bcd/index.htm>. |
851 | L<http://www.geoffchappell.com/notes/windows/boot/bcd/index.htm>. |
788 | |
852 | |
789 | =head1 AUTHOR |
853 | =head1 AUTHOR |
790 | |
854 | |
791 | Written by Marc A. Lehmann <pbcdedit@schmorp.de>. |
855 | Written by Marc A. Lehmann L<pbcdedit@schmorp.de>. |
792 | |
856 | |
793 | =head1 REPORTING BUGS |
857 | =head1 REPORTING BUGS |
794 | |
858 | |
795 | Bugs can be reported dorectly tt he author at L<pcbedit@schmorp.de>. |
859 | Bugs can be reported directly the author at L<pcbedit@schmorp.de>. |
796 | |
860 | |
797 | =head1 BUGS AND SHORTCOMINGS |
861 | =head1 BUGS AND SHORTCOMINGS |
798 | |
862 | |
799 | This should be a module. Of a series of modules, even. |
863 | This should be a module. Of a series of modules, even. |
800 | |
864 | |
801 | Registry code should preserve classname and security descriptor data, and |
865 | Registry code should preserve classname and security descriptor data, and |
802 | whatever else is necessary to read and write any registry hive file. |
866 | whatever else is necessary to read and write any registry hive file. |
803 | |
867 | |
804 | I am also not happy with device descriptors being strings rather than a |
868 | 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 |
869 | data structure, but strings are probably better for command line usage. In |
806 | any case,. device descriptors could be converted by simply "splitting" at |
870 | any case, device descriptors could be converted by simply "splitting" at |
807 | "=" and "," into an array reference, recursively. |
871 | "=" and "," into an array reference, recursively. |
808 | |
872 | |
809 | =head1 HOMEPAGE |
873 | =head1 HOMEPAGE |
810 | |
874 | |
811 | Original versions of this program can be found at |
875 | Original versions of this program can be found at |
… | |
… | |
818 | free to change and redistribute it. There is NO WARRANTY, to the extent |
882 | free to change and redistribute it. There is NO WARRANTY, to the extent |
819 | permitted by law. |
883 | permitted by law. |
820 | |
884 | |
821 | =cut |
885 | =cut |
822 | |
886 | |
823 | BEGIN { require "common/sense.pm"; common::sense->import } # common sense is optional, but recommended |
887 | # common sense is optional, but recommended |
|
|
888 | BEGIN { eval { require "common/sense.pm"; } && common::sense->import } |
824 | |
889 | |
825 | use Data::Dump; |
890 | no warnings 'portable'; # avoid 32 bit integer warnings |
|
|
891 | |
826 | use Encode (); |
892 | use Encode (); |
827 | use List::Util (); |
893 | use List::Util (); |
828 | use IO::Handle (); |
894 | use IO::Handle (); |
829 | use Time::HiRes (); |
895 | use Time::HiRes (); |
830 | |
896 | |
… | |
… | |
853 | or die "$path: short read\n"; |
919 | or die "$path: short read\n"; |
854 | |
920 | |
855 | $buf |
921 | $buf |
856 | } |
922 | } |
857 | |
923 | |
858 | # sources and resources used for this: |
924 | # sources and resources used for writing pbcdedit |
|
|
925 | # |
859 | # registry: |
926 | # registry: |
860 | # https://github.com/msuhanov/regf/blob/master/Windows%20registry%20file%20format%20specification.md |
927 | # https://github.com/msuhanov/regf/blob/master/Windows%20registry%20file%20format%20specification.md |
861 | # http://amnesia.gtisc.gatech.edu/~moyix/suzibandit.ltd.uk/MSc/ |
928 | # http://amnesia.gtisc.gatech.edu/~moyix/suzibandit.ltd.uk/MSc/ |
862 | # bcd: |
929 | # bcd: |
863 | # http://www.geoffchappell.com/notes/windows/boot/bcd/index.htm |
930 | # http://www.geoffchappell.com/notes/windows/boot/bcd/index.htm |
… | |
… | |
1351 | sub BCDE_FORMAT_GUID_LIST () { 0x04000000 } |
1418 | sub BCDE_FORMAT_GUID_LIST () { 0x04000000 } |
1352 | sub BCDE_FORMAT_INTEGER () { 0x05000000 } |
1419 | sub BCDE_FORMAT_INTEGER () { 0x05000000 } |
1353 | sub BCDE_FORMAT_BOOLEAN () { 0x06000000 } |
1420 | sub BCDE_FORMAT_BOOLEAN () { 0x06000000 } |
1354 | sub BCDE_FORMAT_INTEGER_LIST () { 0x07000000 } |
1421 | sub BCDE_FORMAT_INTEGER_LIST () { 0x07000000 } |
1355 | |
1422 | |
1356 | sub dec_device; |
|
|
1357 | sub enc_device; |
|
|
1358 | |
|
|
1359 | sub enc_integer($) { |
1423 | sub enc_integer($) { |
1360 | no warnings 'portable'; # ugh |
|
|
1361 | my $value = shift; |
1424 | my $value = shift; |
1362 | $value = oct $value if $value =~ /^0[bBxX]/; |
1425 | $value = oct $value if $value =~ /^0[bBxX]/; |
1363 | unpack "H*", pack "Q<", $value |
1426 | unpack "H*", pack "Q<", $value |
1364 | } |
1427 | } |
|
|
1428 | |
|
|
1429 | sub enc_device($$); |
|
|
1430 | sub dec_device($$); |
1365 | |
1431 | |
1366 | our %bcde_dec = ( |
1432 | our %bcde_dec = ( |
1367 | BCDE_FORMAT_DEVICE , \&dec_device, |
1433 | BCDE_FORMAT_DEVICE , \&dec_device, |
1368 | # # for round-trip verification |
1434 | # # for round-trip verification |
1369 | # BCDE_FORMAT_DEVICE , sub { |
1435 | # BCDE_FORMAT_DEVICE , sub { |
… | |
… | |
1379 | BCDE_FORMAT_BOOLEAN , sub { shift eq "00" ? 0 : 1 }, |
1445 | BCDE_FORMAT_BOOLEAN , sub { shift eq "00" ? 0 : 1 }, |
1380 | BCDE_FORMAT_INTEGER_LIST, sub { join " ", unpack "Q*", pack "H*", shift }, # not sure if this cna be 4 bytes |
1446 | BCDE_FORMAT_INTEGER_LIST, sub { join " ", unpack "Q*", pack "H*", shift }, # not sure if this cna be 4 bytes |
1381 | ); |
1447 | ); |
1382 | |
1448 | |
1383 | our %bcde_enc = ( |
1449 | our %bcde_enc = ( |
1384 | BCDE_FORMAT_DEVICE , sub { binary => enc_device shift }, |
1450 | BCDE_FORMAT_DEVICE , sub { binary => enc_device $_[0], $_[1] }, |
1385 | BCDE_FORMAT_STRING , sub { sz => shift }, |
1451 | BCDE_FORMAT_STRING , sub { sz => shift }, |
1386 | BCDE_FORMAT_GUID , sub { sz => "{" . (dec_guid enc_wguid shift) . "}" }, |
1452 | BCDE_FORMAT_GUID , sub { sz => "{" . (dec_guid enc_wguid shift) . "}" }, |
1387 | BCDE_FORMAT_GUID_LIST , sub { multi_sz => [map "{" . (dec_guid enc_wguid $_) . "}", split /\s+/, shift ] }, |
1453 | BCDE_FORMAT_GUID_LIST , sub { multi_sz => [map "{" . (dec_guid enc_wguid $_) . "}", split /\s+/, shift ] }, |
1388 | BCDE_FORMAT_INTEGER , sub { binary => enc_integer shift }, |
1454 | BCDE_FORMAT_INTEGER , sub { binary => enc_integer shift }, |
1389 | BCDE_FORMAT_BOOLEAN , sub { binary => shift ? "01" : "00" }, |
1455 | BCDE_FORMAT_BOOLEAN , sub { binary => shift ? "01" : "00" }, |
1390 | BCDE_FORMAT_INTEGER_LIST, sub { binary => join "", map enc_integer $_, split /\s+/, shift }, |
1456 | BCDE_FORMAT_INTEGER_LIST, sub { binary => join "", map enc_integer $_, split /\s+/, shift }, |
1391 | ); |
1457 | ); |
1392 | |
1458 | |
1393 | # BCD Elements |
1459 | # BCD Elements |
1394 | our %bcde = ( |
1460 | our %bcde_byclass = ( |
|
|
1461 | any => { |
1395 | 0x11000001 => 'device', |
1462 | 0x11000001 => 'device', |
1396 | 0x12000002 => 'path', |
1463 | 0x12000002 => 'path', |
1397 | 0x12000004 => 'description', |
1464 | 0x12000004 => 'description', |
1398 | 0x12000005 => 'locale', |
1465 | 0x12000005 => 'locale', |
1399 | 0x14000006 => 'inherit', |
1466 | 0x14000006 => 'inherit', |
1400 | 0x15000007 => 'truncatememory', |
1467 | 0x15000007 => 'truncatememory', |
1401 | 0x14000008 => 'recoverysequence', |
1468 | 0x14000008 => 'recoverysequence', |
1402 | 0x16000009 => 'recoveryenabled', |
1469 | 0x16000009 => 'recoveryenabled', |
1403 | 0x1700000a => 'badmemorylist', |
1470 | 0x1700000a => 'badmemorylist', |
1404 | 0x1600000b => 'badmemoryaccess', |
1471 | 0x1600000b => 'badmemoryaccess', |
1405 | 0x1500000c => 'firstmegabytepolicy', |
1472 | 0x1500000c => 'firstmegabytepolicy', |
1406 | 0x1500000d => 'relocatephysical', |
1473 | 0x1500000d => 'relocatephysical', |
1407 | 0x1500000e => 'avoidlowmemory', |
1474 | 0x1500000e => 'avoidlowmemory', |
1408 | 0x1600000f => 'traditionalkseg', |
1475 | 0x1600000f => 'traditionalkseg', |
1409 | 0x16000010 => 'bootdebug', |
1476 | 0x16000010 => 'bootdebug', |
1410 | 0x15000011 => 'debugtype', |
1477 | 0x15000011 => 'debugtype', |
1411 | 0x15000012 => 'debugaddress', |
1478 | 0x15000012 => 'debugaddress', |
1412 | 0x15000013 => 'debugport', |
1479 | 0x15000013 => 'debugport', |
1413 | 0x15000014 => 'baudrate', |
1480 | 0x15000014 => 'baudrate', |
1414 | 0x15000015 => 'channel', |
1481 | 0x15000015 => 'channel', |
1415 | 0x12000016 => 'targetname', |
1482 | 0x12000016 => 'targetname', |
1416 | 0x16000017 => 'noumex', |
1483 | 0x16000017 => 'noumex', |
1417 | 0x15000018 => 'debugstart', |
1484 | 0x15000018 => 'debugstart', |
1418 | 0x12000019 => 'busparams', |
1485 | 0x12000019 => 'busparams', |
1419 | 0x1500001a => 'hostip', |
1486 | 0x1500001a => 'hostip', |
1420 | 0x1500001b => 'port', |
1487 | 0x1500001b => 'port', |
1421 | 0x1600001c => 'dhcp', |
1488 | 0x1600001c => 'dhcp', |
1422 | 0x1200001d => 'key', |
1489 | 0x1200001d => 'key', |
1423 | 0x1600001e => 'vm', |
1490 | 0x1600001e => 'vm', |
1424 | 0x16000020 => 'bootems', |
1491 | 0x16000020 => 'bootems', |
1425 | 0x15000022 => 'emsport', |
1492 | 0x15000022 => 'emsport', |
1426 | 0x15000023 => 'emsbaudrate', |
1493 | 0x15000023 => 'emsbaudrate', |
1427 | 0x12000030 => 'loadoptions', |
1494 | 0x12000030 => 'loadoptions', |
1428 | 0x16000040 => 'advancedoptions', |
1495 | 0x16000040 => 'advancedoptions', |
1429 | 0x16000041 => 'optionsedit', |
1496 | 0x16000041 => 'optionsedit', |
1430 | 0x15000042 => 'keyringaddress', |
1497 | 0x15000042 => 'keyringaddress', |
1431 | 0x11000043 => 'bootstatdevice', |
1498 | 0x11000043 => 'bootstatdevice', |
1432 | 0x12000044 => 'bootstatfilepath', |
1499 | 0x12000044 => 'bootstatfilepath', |
1433 | 0x16000045 => 'preservebootstat', |
1500 | 0x16000045 => 'preservebootstat', |
1434 | 0x16000046 => 'graphicsmodedisabled', |
1501 | 0x16000046 => 'graphicsmodedisabled', |
1435 | 0x15000047 => 'configaccesspolicy', |
1502 | 0x15000047 => 'configaccesspolicy', |
1436 | 0x16000048 => 'nointegritychecks', |
1503 | 0x16000048 => 'nointegritychecks', |
1437 | 0x16000049 => 'testsigning', |
1504 | 0x16000049 => 'testsigning', |
1438 | 0x1200004a => 'fontpath', |
1505 | 0x1200004a => 'fontpath', |
1439 | 0x1500004b => 'integrityservices', |
1506 | 0x1500004b => 'integrityservices', |
1440 | 0x1500004c => 'volumebandid', |
1507 | 0x1500004c => 'volumebandid', |
1441 | 0x16000050 => 'extendedinput', |
1508 | 0x16000050 => 'extendedinput', |
1442 | 0x15000051 => 'initialconsoleinput', |
1509 | 0x15000051 => 'initialconsoleinput', |
1443 | 0x15000052 => 'graphicsresolution', |
1510 | 0x15000052 => 'graphicsresolution', |
1444 | 0x16000053 => 'restartonfailure', |
1511 | 0x16000053 => 'restartonfailure', |
1445 | 0x16000054 => 'highestmode', |
1512 | 0x16000054 => 'highestmode', |
1446 | 0x16000060 => 'isolatedcontext', |
1513 | 0x16000060 => 'isolatedcontext', |
1447 | 0x15000065 => 'displaymessage', |
1514 | 0x15000065 => 'displaymessage', |
1448 | 0x15000066 => 'displaymessageoverride', |
1515 | 0x15000066 => 'displaymessageoverride', |
1449 | 0x16000068 => 'nobootuxtext', |
1516 | 0x16000068 => 'nobootuxtext', |
1450 | 0x16000069 => 'nobootuxprogress', |
1517 | 0x16000069 => 'nobootuxprogress', |
1451 | 0x1600006a => 'nobootuxfade', |
1518 | 0x1600006a => 'nobootuxfade', |
1452 | 0x1600006b => 'bootuxreservepooldebug', |
1519 | 0x1600006b => 'bootuxreservepooldebug', |
1453 | 0x1600006c => 'bootuxdisabled', |
1520 | 0x1600006c => 'bootuxdisabled', |
1454 | 0x1500006d => 'bootuxfadeframes', |
1521 | 0x1500006d => 'bootuxfadeframes', |
1455 | 0x1600006e => 'bootuxdumpstats', |
1522 | 0x1600006e => 'bootuxdumpstats', |
1456 | 0x1600006f => 'bootuxshowstats', |
1523 | 0x1600006f => 'bootuxshowstats', |
1457 | 0x16000071 => 'multibootsystem', |
1524 | 0x16000071 => 'multibootsystem', |
1458 | 0x16000072 => 'nokeyboard', |
1525 | 0x16000072 => 'nokeyboard', |
1459 | 0x15000073 => 'aliaswindowskey', |
1526 | 0x15000073 => 'aliaswindowskey', |
1460 | 0x16000074 => 'bootshutdowndisabled', |
1527 | 0x16000074 => 'bootshutdowndisabled', |
1461 | 0x15000075 => 'performancefrequency', |
1528 | 0x15000075 => 'performancefrequency', |
1462 | 0x15000076 => 'securebootrawpolicy', |
1529 | 0x15000076 => 'securebootrawpolicy', |
1463 | 0x17000077 => 'allowedinmemorysettings', |
1530 | 0x17000077 => 'allowedinmemorysettings', |
1464 | 0x15000079 => 'bootuxtransitiontime', |
1531 | 0x15000079 => 'bootuxtransitiontime', |
1465 | 0x1600007a => 'mobilegraphics', |
1532 | 0x1600007a => 'mobilegraphics', |
1466 | 0x1600007b => 'forcefipscrypto', |
1533 | 0x1600007b => 'forcefipscrypto', |
1467 | 0x1500007d => 'booterrorux', |
1534 | 0x1500007d => 'booterrorux', |
1468 | 0x1600007e => 'flightsigning', |
1535 | 0x1600007e => 'flightsigning', |
1469 | 0x1500007f => 'measuredbootlogformat', |
1536 | 0x1500007f => 'measuredbootlogformat', |
1470 | 0x15000080 => 'displayrotation', |
1537 | 0x15000080 => 'displayrotation', |
1471 | 0x15000081 => 'logcontrol', |
1538 | 0x15000081 => 'logcontrol', |
1472 | 0x16000082 => 'nofirmwaresync', |
1539 | 0x16000082 => 'nofirmwaresync', |
1473 | 0x11000084 => 'windowssyspart', |
1540 | 0x11000084 => 'windowssyspart', |
1474 | 0x16000087 => 'numlock', |
1541 | 0x16000087 => 'numlock', |
1475 | 0x22000001 => 'bpbstring', |
1542 | 0x26000202 => 'skipffumode', |
|
|
1543 | 0x26000203 => 'forceffumode', |
|
|
1544 | 0x25000510 => 'chargethreshold', |
|
|
1545 | 0x26000512 => 'offmodecharging', |
|
|
1546 | 0x25000aaa => 'bootflow', |
|
|
1547 | 0x45000001 => 'devicetype', |
|
|
1548 | 0x42000002 => 'applicationrelativepath', |
|
|
1549 | 0x42000003 => 'ramdiskdevicerelativepath', |
|
|
1550 | 0x46000004 => 'omitosloaderelements', |
|
|
1551 | 0x47000006 => 'elementstomigrate', |
|
|
1552 | 0x46000010 => 'recoveryos', |
|
|
1553 | }, |
|
|
1554 | bootapp => { |
|
|
1555 | 0x26000145 => 'enablebootdebugpolicy', |
|
|
1556 | 0x26000146 => 'enablebootorderclean', |
|
|
1557 | 0x26000147 => 'enabledeviceid', |
|
|
1558 | 0x26000148 => 'enableffuloader', |
|
|
1559 | 0x26000149 => 'enableiuloader', |
|
|
1560 | 0x2600014a => 'enablemassstorage', |
|
|
1561 | 0x2600014b => 'enablerpmbprovisioning', |
|
|
1562 | 0x2600014c => 'enablesecurebootpolicy', |
|
|
1563 | 0x2600014d => 'enablestartcharge', |
|
|
1564 | 0x2600014e => 'enableresettpm', |
|
|
1565 | }, |
|
|
1566 | bootmgr => { |
1476 | 0x24000001 => 'displayorder', |
1567 | 0x24000001 => 'displayorder', |
1477 | 0x21000001 => 'filedevice', |
|
|
1478 | 0x21000001 => 'osdevice', |
|
|
1479 | 0x25000001 => 'passcount', |
|
|
1480 | 0x26000001 => 'pxesoftreboot', |
|
|
1481 | 0x22000002 => 'applicationname', |
|
|
1482 | 0x24000002 => 'bootsequence', |
1568 | 0x24000002 => 'bootsequence', |
1483 | 0x22000002 => 'filepath', |
|
|
1484 | 0x22000002 => 'systemroot', |
|
|
1485 | 0x25000002 => 'testmix', |
|
|
1486 | 0x26000003 => 'cacheenable', |
|
|
1487 | 0x26000003 => 'customsettings', |
|
|
1488 | 0x23000003 => 'default', |
1569 | 0x23000003 => 'default', |
1489 | 0x25000003 => 'failurecount', |
|
|
1490 | 0x23000003 => 'resumeobject', |
|
|
1491 | 0x26000004 => 'failuresenabled', |
|
|
1492 | 0x26000004 => 'pae', |
|
|
1493 | 0x26000004 => 'stampdisks', |
|
|
1494 | 0x25000004 => 'testtofail', |
|
|
1495 | 0x25000004 => 'timeout', |
1570 | 0x25000004 => 'timeout', |
1496 | 0x21000005 => 'associatedosdevice', |
|
|
1497 | 0x26000005 => 'cacheenable', |
|
|
1498 | 0x26000005 => 'resume', |
1571 | 0x26000005 => 'resume', |
1499 | 0x25000005 => 'stridefailcount', |
|
|
1500 | 0x26000006 => 'debugoptionenabled', |
|
|
1501 | 0x25000006 => 'invcfailcount', |
|
|
1502 | 0x23000006 => 'resumeobject', |
1572 | 0x23000006 => 'resumeobject', |
1503 | 0x25000007 => 'bootux', |
|
|
1504 | 0x25000007 => 'matsfailcount', |
|
|
1505 | 0x24000007 => 'startupsequence', |
1573 | 0x24000007 => 'startupsequence', |
1506 | 0x25000008 => 'bootmenupolicy', |
|
|
1507 | 0x25000008 => 'randfailcount', |
|
|
1508 | 0x25000009 => 'chckrfailcount', |
|
|
1509 | 0x26000010 => 'detecthal', |
|
|
1510 | 0x24000010 => 'toolsdisplayorder', |
1574 | 0x24000010 => 'toolsdisplayorder', |
1511 | 0x22000011 => 'kernel', |
|
|
1512 | 0x22000012 => 'hal', |
|
|
1513 | 0x22000013 => 'dbgtransport', |
|
|
1514 | 0x26000020 => 'displaybootmenu', |
1575 | 0x26000020 => 'displaybootmenu', |
1515 | 0x25000020 => 'nx', |
|
|
1516 | 0x26000021 => 'noerrordisplay', |
1576 | 0x26000021 => 'noerrordisplay', |
1517 | 0x25000021 => 'pae', |
|
|
1518 | 0x21000022 => 'bcddevice', |
1577 | 0x21000022 => 'bcddevice', |
1519 | 0x26000022 => 'winpe', |
|
|
1520 | 0x22000023 => 'bcdfilepath', |
1578 | 0x22000023 => 'bcdfilepath', |
1521 | 0x26000024 => 'hormenabled', |
1579 | 0x26000024 => 'hormenabled', |
1522 | 0x26000024 => 'hormenabled', |
|
|
1523 | 0x26000024 => 'nocrashautoreboot', |
|
|
1524 | 0x26000025 => 'hiberboot', |
1580 | 0x26000025 => 'hiberboot', |
1525 | 0x26000025 => 'lastknowngood', |
|
|
1526 | 0x26000026 => 'oslnointegritychecks', |
|
|
1527 | 0x22000026 => 'passwordoverride', |
1581 | 0x22000026 => 'passwordoverride', |
1528 | 0x26000027 => 'osltestsigning', |
|
|
1529 | 0x22000027 => 'pinpassphraseoverride', |
1582 | 0x22000027 => 'pinpassphraseoverride', |
1530 | 0x26000028 => 'processcustomactionsfirst', |
1583 | 0x26000028 => 'processcustomactionsfirst', |
1531 | 0x27000030 => 'customactions', |
1584 | 0x27000030 => 'customactions', |
1532 | 0x26000030 => 'nolowmem', |
|
|
1533 | 0x26000031 => 'persistbootsequence', |
1585 | 0x26000031 => 'persistbootsequence', |
1534 | 0x25000031 => 'removememory', |
|
|
1535 | 0x25000032 => 'increaseuserva', |
|
|
1536 | 0x26000032 => 'skipstartupsequence', |
1586 | 0x26000032 => 'skipstartupsequence', |
1537 | 0x25000033 => 'perfmem', |
|
|
1538 | 0x22000040 => 'fverecoveryurl', |
1587 | 0x22000040 => 'fverecoveryurl', |
1539 | 0x26000040 => 'vga', |
|
|
1540 | 0x22000041 => 'fverecoverymessage', |
1588 | 0x22000041 => 'fverecoverymessage', |
|
|
1589 | }, |
|
|
1590 | device => { |
|
|
1591 | 0x35000001 => 'ramdiskimageoffset', |
|
|
1592 | 0x35000002 => 'ramdisktftpclientport', |
|
|
1593 | 0x31000003 => 'ramdisksdidevice', |
|
|
1594 | 0x32000004 => 'ramdisksdipath', |
|
|
1595 | 0x35000005 => 'ramdiskimagelength', |
|
|
1596 | 0x36000006 => 'exportascd', |
|
|
1597 | 0x35000007 => 'ramdisktftpblocksize', |
|
|
1598 | 0x35000008 => 'ramdisktftpwindowsize', |
|
|
1599 | 0x36000009 => 'ramdiskmcenabled', |
|
|
1600 | 0x3600000a => 'ramdiskmctftpfallback', |
|
|
1601 | 0x3600000b => 'ramdisktftpvarwindow', |
|
|
1602 | }, |
|
|
1603 | memdiag => { |
|
|
1604 | 0x25000001 => 'passcount', |
|
|
1605 | 0x25000002 => 'testmix', |
|
|
1606 | 0x25000003 => 'failurecount', |
|
|
1607 | 0x26000003 => 'cacheenable', |
|
|
1608 | 0x25000004 => 'testtofail', |
|
|
1609 | 0x26000004 => 'failuresenabled', |
|
|
1610 | 0x25000005 => 'stridefailcount', |
|
|
1611 | 0x26000005 => 'cacheenable', |
|
|
1612 | 0x25000006 => 'invcfailcount', |
|
|
1613 | 0x25000007 => 'matsfailcount', |
|
|
1614 | 0x25000008 => 'randfailcount', |
|
|
1615 | 0x25000009 => 'chckrfailcount', |
|
|
1616 | }, |
|
|
1617 | ntldr => { |
|
|
1618 | 0x22000001 => 'bpbstring', |
|
|
1619 | }, |
|
|
1620 | osloader => { |
|
|
1621 | 0x21000001 => 'osdevice', |
|
|
1622 | 0x22000002 => 'systemroot', |
|
|
1623 | 0x23000003 => 'resumeobject', |
|
|
1624 | 0x26000004 => 'stampdisks', |
|
|
1625 | 0x26000010 => 'detecthal', |
|
|
1626 | 0x22000011 => 'kernel', |
|
|
1627 | 0x22000012 => 'hal', |
|
|
1628 | 0x22000013 => 'dbgtransport', |
|
|
1629 | 0x25000020 => 'nx', |
|
|
1630 | 0x25000021 => 'pae', |
|
|
1631 | 0x26000022 => 'winpe', |
|
|
1632 | 0x26000024 => 'nocrashautoreboot', |
|
|
1633 | 0x26000025 => 'lastknowngood', |
|
|
1634 | 0x26000026 => 'oslnointegritychecks', |
|
|
1635 | 0x26000027 => 'osltestsigning', |
|
|
1636 | 0x26000030 => 'nolowmem', |
|
|
1637 | 0x25000031 => 'removememory', |
|
|
1638 | 0x25000032 => 'increaseuserva', |
|
|
1639 | 0x25000033 => 'perfmem', |
|
|
1640 | 0x26000040 => 'vga', |
1541 | 0x26000041 => 'quietboot', |
1641 | 0x26000041 => 'quietboot', |
1542 | 0x26000042 => 'novesa', |
1642 | 0x26000042 => 'novesa', |
1543 | 0x26000043 => 'novga', |
1643 | 0x26000043 => 'novga', |
1544 | 0x25000050 => 'clustermodeaddressing', |
1644 | 0x25000050 => 'clustermodeaddressing', |
1545 | 0x26000051 => 'usephysicaldestination', |
1645 | 0x26000051 => 'usephysicaldestination', |
1546 | 0x25000052 => 'restrictapiccluster', |
1646 | 0x25000052 => 'restrictapiccluster', |
1547 | 0x22000053 => 'evstore', |
1647 | 0x22000053 => 'evstore', |
1548 | 0x26000054 => 'uselegacyapicmode', |
1648 | 0x26000054 => 'uselegacyapicmode', |
1549 | 0x26000060 => 'onecpu', |
1649 | 0x26000060 => 'onecpu', |
1550 | 0x25000061 => 'numproc', |
1650 | 0x25000061 => 'numproc', |
1551 | 0x26000062 => 'maxproc', |
1651 | 0x26000062 => 'maxproc', |
1552 | 0x25000063 => 'configflags', |
1652 | 0x25000063 => 'configflags', |
1553 | 0x26000064 => 'maxgroup', |
1653 | 0x26000064 => 'maxgroup', |
1554 | 0x26000065 => 'groupaware', |
1654 | 0x26000065 => 'groupaware', |
1555 | 0x25000066 => 'groupsize', |
1655 | 0x25000066 => 'groupsize', |
1556 | 0x26000070 => 'usefirmwarepcisettings', |
1656 | 0x26000070 => 'usefirmwarepcisettings', |
1557 | 0x25000071 => 'msi', |
1657 | 0x25000071 => 'msi', |
1558 | 0x25000072 => 'pciexpress', |
1658 | 0x25000072 => 'pciexpress', |
1559 | 0x25000080 => 'safeboot', |
1659 | 0x25000080 => 'safeboot', |
1560 | 0x26000081 => 'safebootalternateshell', |
1660 | 0x26000081 => 'safebootalternateshell', |
1561 | 0x26000090 => 'bootlog', |
1661 | 0x26000090 => 'bootlog', |
1562 | 0x26000091 => 'sos', |
1662 | 0x26000091 => 'sos', |
1563 | 0x260000a0 => 'debug', |
1663 | 0x260000a0 => 'debug', |
1564 | 0x260000a1 => 'halbreakpoint', |
1664 | 0x260000a1 => 'halbreakpoint', |
1565 | 0x260000a2 => 'useplatformclock', |
1665 | 0x260000a2 => 'useplatformclock', |
1566 | 0x260000a3 => 'forcelegacyplatform', |
1666 | 0x260000a3 => 'forcelegacyplatform', |
1567 | 0x260000a4 => 'useplatformtick', |
1667 | 0x260000a4 => 'useplatformtick', |
1568 | 0x260000a5 => 'disabledynamictick', |
1668 | 0x260000a5 => 'disabledynamictick', |
1569 | 0x250000a6 => 'tscsyncpolicy', |
1669 | 0x250000a6 => 'tscsyncpolicy', |
1570 | 0x260000b0 => 'ems', |
1670 | 0x260000b0 => 'ems', |
1571 | 0x250000c0 => 'forcefailure', |
1671 | 0x250000c0 => 'forcefailure', |
1572 | 0x250000c1 => 'driverloadfailurepolicy', |
1672 | 0x250000c1 => 'driverloadfailurepolicy', |
1573 | 0x250000c2 => 'bootmenupolicy', |
1673 | 0x250000c2 => 'bootmenupolicy', |
1574 | 0x260000c3 => 'onetimeadvancedoptions', |
1674 | 0x260000c3 => 'onetimeadvancedoptions', |
1575 | 0x260000c4 => 'onetimeoptionsedit', |
1675 | 0x260000c4 => 'onetimeoptionsedit', |
1576 | 0x250000e0 => 'bootstatuspolicy', |
1676 | 0x250000e0 => 'bootstatuspolicy', |
1577 | 0x260000e1 => 'disableelamdrivers', |
1677 | 0x260000e1 => 'disableelamdrivers', |
1578 | 0x250000f0 => 'hypervisorlaunchtype', |
1678 | 0x250000f0 => 'hypervisorlaunchtype', |
1579 | 0x220000f1 => 'hypervisorpath', |
1679 | 0x220000f1 => 'hypervisorpath', |
1580 | 0x260000f2 => 'hypervisordebug', |
1680 | 0x260000f2 => 'hypervisordebug', |
1581 | 0x250000f3 => 'hypervisordebugtype', |
1681 | 0x250000f3 => 'hypervisordebugtype', |
1582 | 0x250000f4 => 'hypervisordebugport', |
1682 | 0x250000f4 => 'hypervisordebugport', |
1583 | 0x250000f5 => 'hypervisorbaudrate', |
1683 | 0x250000f5 => 'hypervisorbaudrate', |
1584 | 0x250000f6 => 'hypervisorchannel', |
1684 | 0x250000f6 => 'hypervisorchannel', |
1585 | 0x250000f7 => 'bootux', |
1685 | 0x250000f7 => 'bootux', |
1586 | 0x260000f8 => 'hypervisordisableslat', |
1686 | 0x260000f8 => 'hypervisordisableslat', |
1587 | 0x220000f9 => 'hypervisorbusparams', |
1687 | 0x220000f9 => 'hypervisorbusparams', |
1588 | 0x250000fa => 'hypervisornumproc', |
1688 | 0x250000fa => 'hypervisornumproc', |
1589 | 0x250000fb => 'hypervisorrootprocpernode', |
1689 | 0x250000fb => 'hypervisorrootprocpernode', |
1590 | 0x260000fc => 'hypervisoruselargevtlb', |
1690 | 0x260000fc => 'hypervisoruselargevtlb', |
1591 | 0x250000fd => 'hypervisorhostip', |
1691 | 0x250000fd => 'hypervisorhostip', |
1592 | 0x250000fe => 'hypervisorhostport', |
1692 | 0x250000fe => 'hypervisorhostport', |
1593 | 0x250000ff => 'hypervisordebugpages', |
1693 | 0x250000ff => 'hypervisordebugpages', |
1594 | 0x25000100 => 'tpmbootentropy', |
1694 | 0x25000100 => 'tpmbootentropy', |
1595 | 0x22000110 => 'hypervisorusekey', |
1695 | 0x22000110 => 'hypervisorusekey', |
1596 | 0x22000112 => 'hypervisorproductskutype', |
1696 | 0x22000112 => 'hypervisorproductskutype', |
1597 | 0x25000113 => 'hypervisorrootproc', |
1697 | 0x25000113 => 'hypervisorrootproc', |
1598 | 0x26000114 => 'hypervisordhcp', |
1698 | 0x26000114 => 'hypervisordhcp', |
1599 | 0x25000115 => 'hypervisoriommupolicy', |
1699 | 0x25000115 => 'hypervisoriommupolicy', |
1600 | 0x26000116 => 'hypervisorusevapic', |
1700 | 0x26000116 => 'hypervisorusevapic', |
1601 | 0x22000117 => 'hypervisorloadoptions', |
1701 | 0x22000117 => 'hypervisorloadoptions', |
1602 | 0x25000118 => 'hypervisormsrfilterpolicy', |
1702 | 0x25000118 => 'hypervisormsrfilterpolicy', |
1603 | 0x25000119 => 'hypervisormmionxpolicy', |
1703 | 0x25000119 => 'hypervisormmionxpolicy', |
1604 | 0x2500011a => 'hypervisorschedulertype', |
1704 | 0x2500011a => 'hypervisorschedulertype', |
1605 | 0x25000120 => 'xsavepolicy', |
1705 | 0x25000120 => 'xsavepolicy', |
1606 | 0x25000121 => 'xsaveaddfeature0', |
1706 | 0x25000121 => 'xsaveaddfeature0', |
1607 | 0x25000122 => 'xsaveaddfeature1', |
1707 | 0x25000122 => 'xsaveaddfeature1', |
1608 | 0x25000123 => 'xsaveaddfeature2', |
1708 | 0x25000123 => 'xsaveaddfeature2', |
1609 | 0x25000124 => 'xsaveaddfeature3', |
1709 | 0x25000124 => 'xsaveaddfeature3', |
1610 | 0x25000125 => 'xsaveaddfeature4', |
1710 | 0x25000125 => 'xsaveaddfeature4', |
1611 | 0x25000126 => 'xsaveaddfeature5', |
1711 | 0x25000126 => 'xsaveaddfeature5', |
1612 | 0x25000127 => 'xsaveaddfeature6', |
1712 | 0x25000127 => 'xsaveaddfeature6', |
1613 | 0x25000128 => 'xsaveaddfeature7', |
1713 | 0x25000128 => 'xsaveaddfeature7', |
1614 | 0x25000129 => 'xsaveremovefeature', |
1714 | 0x25000129 => 'xsaveremovefeature', |
1615 | 0x2500012a => 'xsaveprocessorsmask', |
1715 | 0x2500012a => 'xsaveprocessorsmask', |
1616 | 0x2500012b => 'xsavedisable', |
1716 | 0x2500012b => 'xsavedisable', |
1617 | 0x2500012c => 'kerneldebugtype', |
1717 | 0x2500012c => 'kerneldebugtype', |
1618 | 0x2200012d => 'kernelbusparams', |
1718 | 0x2200012d => 'kernelbusparams', |
1619 | 0x2500012e => 'kerneldebugaddress', |
1719 | 0x2500012e => 'kerneldebugaddress', |
1620 | 0x2500012f => 'kerneldebugport', |
1720 | 0x2500012f => 'kerneldebugport', |
1621 | 0x25000130 => 'claimedtpmcounter', |
1721 | 0x25000130 => 'claimedtpmcounter', |
1622 | 0x25000131 => 'kernelchannel', |
1722 | 0x25000131 => 'kernelchannel', |
1623 | 0x22000132 => 'kerneltargetname', |
1723 | 0x22000132 => 'kerneltargetname', |
1624 | 0x25000133 => 'kernelhostip', |
1724 | 0x25000133 => 'kernelhostip', |
1625 | 0x25000134 => 'kernelport', |
1725 | 0x25000134 => 'kernelport', |
1626 | 0x26000135 => 'kerneldhcp', |
1726 | 0x26000135 => 'kerneldhcp', |
1627 | 0x22000136 => 'kernelkey', |
1727 | 0x22000136 => 'kernelkey', |
1628 | 0x22000137 => 'imchivename', |
1728 | 0x22000137 => 'imchivename', |
1629 | 0x21000138 => 'imcdevice', |
1729 | 0x21000138 => 'imcdevice', |
1630 | 0x25000139 => 'kernelbaudrate', |
1730 | 0x25000139 => 'kernelbaudrate', |
1631 | 0x22000140 => 'mfgmode', |
1731 | 0x22000140 => 'mfgmode', |
1632 | 0x26000141 => 'event', |
1732 | 0x26000141 => 'event', |
1633 | 0x25000142 => 'vsmlaunchtype', |
1733 | 0x25000142 => 'vsmlaunchtype', |
1634 | 0x25000144 => 'hypervisorenforcedcodeintegrity', |
1734 | 0x25000144 => 'hypervisorenforcedcodeintegrity', |
1635 | 0x26000145 => 'enablebootdebugpolicy', |
|
|
1636 | 0x26000146 => 'enablebootorderclean', |
|
|
1637 | 0x26000147 => 'enabledeviceid', |
|
|
1638 | 0x26000148 => 'enableffuloader', |
|
|
1639 | 0x26000149 => 'enableiuloader', |
|
|
1640 | 0x2600014a => 'enablemassstorage', |
|
|
1641 | 0x2600014b => 'enablerpmbprovisioning', |
|
|
1642 | 0x2600014c => 'enablesecurebootpolicy', |
|
|
1643 | 0x2600014d => 'enablestartcharge', |
|
|
1644 | 0x2600014e => 'enableresettpm', |
|
|
1645 | 0x21000150 => 'systemdatadevice', |
1735 | 0x21000150 => 'systemdatadevice', |
1646 | 0x21000151 => 'osarcdevice', |
1736 | 0x21000151 => 'osarcdevice', |
1647 | 0x21000153 => 'osdatadevice', |
1737 | 0x21000153 => 'osdatadevice', |
1648 | 0x21000154 => 'bspdevice', |
1738 | 0x21000154 => 'bspdevice', |
1649 | 0x21000155 => 'bspfilepath', |
1739 | 0x21000155 => 'bspfilepath', |
1650 | 0x26000202 => 'skipffumode', |
1740 | }, |
1651 | 0x26000203 => 'forceffumode', |
1741 | resume => { |
1652 | 0x25000510 => 'chargethreshold', |
1742 | 0x21000001 => 'filedevice', |
1653 | 0x26000512 => 'offmodecharging', |
1743 | 0x22000002 => 'filepath', |
1654 | 0x25000aaa => 'bootflow', |
1744 | 0x26000003 => 'customsettings', |
1655 | 0x35000001 => 'ramdiskimageoffset', |
1745 | 0x26000004 => 'pae', |
1656 | 0x35000002 => 'ramdisktftpclientport', |
1746 | 0x21000005 => 'associatedosdevice', |
1657 | 0x31000003 => 'ramdisksdidevice', |
1747 | 0x26000006 => 'debugoptionenabled', |
1658 | 0x32000004 => 'ramdisksdipath', |
1748 | 0x25000007 => 'bootux', |
1659 | 0x35000005 => 'ramdiskimagelength', |
1749 | 0x25000008 => 'bootmenupolicy', |
1660 | 0x36000006 => 'exportascd', |
1750 | 0x26000024 => 'hormenabled', |
1661 | 0x35000007 => 'ramdisktftpblocksize', |
1751 | }, |
1662 | 0x35000008 => 'ramdisktftpwindowsize', |
1752 | startup => { |
1663 | 0x36000009 => 'ramdiskmcenabled', |
1753 | 0x26000001 => 'pxesoftreboot', |
1664 | 0x3600000a => 'ramdiskmctftpfallback', |
1754 | 0x22000002 => 'applicationname', |
1665 | 0x3600000b => 'ramdisktftpvarwindow', |
1755 | }, |
1666 | 0x45000001 => 'devicetype', |
|
|
1667 | 0x42000002 => 'applicationrelativepath', |
|
|
1668 | 0x42000003 => 'ramdiskdevicerelativepath', |
|
|
1669 | 0x46000004 => 'omitosloaderelements', |
|
|
1670 | 0x47000006 => 'elementstomigrate', |
|
|
1671 | 0x46000010 => 'recoveryos', |
|
|
1672 | ); |
1756 | ); |
1673 | |
1757 | |
1674 | our %rbcde = reverse %bcde; |
1758 | # mask, value => class |
|
|
1759 | our @bcde_typeclass = ( |
|
|
1760 | [0x00000000, 0x00000000, 'any'], |
|
|
1761 | [0xf00fffff, 0x1000000a, 'bootapp'], |
|
|
1762 | [0xf0ffffff, 0x2020000a, 'bootapp'], |
|
|
1763 | [0xf00fffff, 0x10000001, 'bootmgr'], |
|
|
1764 | [0xf00fffff, 0x10000002, 'bootmgr'], |
|
|
1765 | [0xf0ffffff, 0x20200001, 'bootmgr'], |
|
|
1766 | [0xf0ffffff, 0x20200002, 'bootmgr'], |
|
|
1767 | [0xf0f00000, 0x20300000, 'device'], |
|
|
1768 | [0xf0000000, 0x30000000, 'device'], |
|
|
1769 | [0xf00fffff, 0x10000005, 'memdiag'], |
|
|
1770 | [0xf0ffffff, 0x20200005, 'memdiag'], |
|
|
1771 | [0xf00fffff, 0x10000006, 'ntldr'], |
|
|
1772 | [0xf00fffff, 0x10000007, 'ntldr'], |
|
|
1773 | [0xf0ffffff, 0x20200006, 'ntldr'], |
|
|
1774 | [0xf0ffffff, 0x20200007, 'ntldr'], |
|
|
1775 | [0xf00fffff, 0x10000003, 'osloader'], |
|
|
1776 | [0xf0ffffff, 0x20200003, 'osloader'], |
|
|
1777 | [0xf00fffff, 0x10000004, 'resume'], |
|
|
1778 | [0xf0ffffff, 0x20200004, 'resume'], |
|
|
1779 | [0xf00fffff, 0x10000009, 'startup'], |
|
|
1780 | [0xf0ffffff, 0x20200009, 'startup'], |
|
|
1781 | ); |
1675 | |
1782 | |
|
|
1783 | our %rbcde_byclass; |
|
|
1784 | |
|
|
1785 | while (my ($k, $v) = each %bcde_byclass) { |
|
|
1786 | $rbcde_byclass{$k} = { reverse %$v }; |
|
|
1787 | } |
|
|
1788 | |
|
|
1789 | # decodes (numerical elem, type) to name |
1676 | sub dec_bcde_id($) { |
1790 | sub dec_bcde_id($$) { |
|
|
1791 | for my $class (@bcde_typeclass) { |
|
|
1792 | if (($_[1] & $class->[0]) == $class->[1]) { |
|
|
1793 | if (my $id = $bcde_byclass{$class->[2]}{$_[0]}) { |
|
|
1794 | return $id; |
|
|
1795 | } |
|
|
1796 | } |
|
|
1797 | } |
|
|
1798 | |
1677 | $bcde{$_[0]} // sprintf "custom:%08x", $_[0] |
1799 | sprintf "custom:%08x", $_[0] |
1678 | } |
1800 | } |
1679 | |
1801 | |
|
|
1802 | # encodes (elem as name, type) |
1680 | sub enc_bcde_id($) { |
1803 | sub enc_bcde_id($$) { |
1681 | $_[0] =~ /^custom:([0-9a-fA-F]{8}$)/ |
1804 | $_[0] =~ /^custom:(?:0x)?([0-9a-fA-F]{8}$)/ |
1682 | ? hex $1 |
1805 | and return hex $1; |
1683 | : $rbcde{$_[0]} |
1806 | |
|
|
1807 | for my $class (@bcde_typeclass) { |
|
|
1808 | if (($_[1] & $class->[0]) == $class->[1]) { |
|
|
1809 | if (my $value = $rbcde_byclass{$class->[2]}{$_[0]}) { |
|
|
1810 | return $value; |
|
|
1811 | } |
|
|
1812 | } |
|
|
1813 | } |
|
|
1814 | |
|
|
1815 | undef |
1684 | } |
1816 | } |
1685 | |
1817 | |
1686 | # decode/encode bcd device element - the horror, no documentaion |
1818 | # decode/encode bcd device element - the horror, no documentaion |
1687 | # whatsoever, supercomplex, superinconsistent. |
1819 | # whatsoever, supercomplex, superinconsistent. |
1688 | |
1820 | |
… | |
… | |
1692 | |
1824 | |
1693 | our $NULL_DEVICE = "\x00" x 16; |
1825 | our $NULL_DEVICE = "\x00" x 16; |
1694 | |
1826 | |
1695 | # biggest bitch to decode, ever |
1827 | # biggest bitch to decode, ever |
1696 | # this decoded a device portion after the GUID |
1828 | # this decoded a device portion after the GUID |
1697 | sub dec_device_($); |
1829 | sub dec_device_($$); |
1698 | sub dec_device_($) { |
1830 | sub dec_device_($$) { |
1699 | my ($device) = @_; |
1831 | my ($device, $type) = @_; |
1700 | |
1832 | |
1701 | my $res; |
1833 | my $res; |
1702 | |
1834 | |
1703 | my ($type, $flags, $length, $pad) = unpack "VVVV", substr $device, 0, 4 * 4, ""; |
1835 | my ($type, $flags, $length, $pad) = unpack "VVVV", substr $device, 0, 4 * 4, ""; |
1704 | |
1836 | |
… | |
… | |
1749 | |
1881 | |
1750 | my $partid = $parttype eq "gpt" ? dec_guid $partdata |
1882 | my $partid = $parttype eq "gpt" ? dec_guid $partdata |
1751 | : $type eq "partition" ? unpack "Q<", $partdata # byte offset to partition start |
1883 | : $type eq "partition" ? unpack "Q<", $partdata # byte offset to partition start |
1752 | : unpack "L<", $partdata; # partition number, one-based |
1884 | : unpack "L<", $partdata; # partition number, one-based |
1753 | |
1885 | |
1754 | (my $parent, $device) = dec_device_ $device; |
1886 | (my $parent, $device) = dec_device_ $device, $type; |
1755 | |
1887 | |
1756 | $res .= "="; |
1888 | $res .= "="; |
1757 | $res .= "<$parent>"; |
1889 | $res .= "<$parent>"; |
1758 | $res .= ",$blocktype,$parttype,$diskid,$partid"; |
1890 | $res .= ",$blocktype,$parttype,$diskid,$partid"; |
1759 | |
1891 | |
… | |
… | |
1779 | or die "unsupported file descriptor version '$fver'\n"; |
1911 | or die "unsupported file descriptor version '$fver'\n"; |
1780 | |
1912 | |
1781 | $ftype == 5 |
1913 | $ftype == 5 |
1782 | or die "unsupported file descriptor path type '$type'\n"; |
1914 | or die "unsupported file descriptor path type '$type'\n"; |
1783 | |
1915 | |
1784 | (my $parent, $path) = dec_device_ $path; |
1916 | (my $parent, $path) = dec_device_ $path, $type; |
1785 | |
1917 | |
1786 | $path = $dec_path->($path, "file device without path"); |
1918 | $path = $dec_path->($path, "file device without path"); |
1787 | |
1919 | |
1788 | ($parent, $path) |
1920 | ($parent, $path) |
1789 | }; |
1921 | }; |
… | |
… | |
1795 | |
1927 | |
1796 | } elsif ($blocktype eq "vhd") { |
1928 | } elsif ($blocktype eq "vhd") { |
1797 | $device =~ s/^\x00{20}//s |
1929 | $device =~ s/^\x00{20}//s |
1798 | or die "virtualdisk has non-zero fields I don't understand\n"; |
1930 | or die "virtualdisk has non-zero fields I don't understand\n"; |
1799 | |
1931 | |
1800 | (my $parent, $device) = dec_device_ $device; |
1932 | (my $parent, $device) = dec_device_ $device, $type; |
1801 | |
1933 | |
1802 | $res .= "=vhd,<$parent>"; |
1934 | $res .= "=vhd,<$parent>"; |
1803 | |
1935 | |
1804 | } elsif ($blocktype eq "ramdisk") { |
1936 | } elsif ($blocktype eq "ramdisk") { |
1805 | my ($base, $size, $offset) = unpack "Q< Q< L<", substr $device, 0, 8 + 8 + 4, ""; |
1937 | my ($base, $size, $offset) = unpack "Q< Q< L<", substr $device, 0, 8 + 8 + 4, ""; |
… | |
… | |
1818 | my ($mode, $elem, $parent) = unpack "VVV", substr $device, 0, 4 * 3, ""; |
1950 | my ($mode, $elem, $parent) = unpack "VVV", substr $device, 0, 4 * 3, ""; |
1819 | |
1951 | |
1820 | if ($parent) { |
1952 | if ($parent) { |
1821 | # not sure why this is an offset - it must come after the path |
1953 | # not sure why this is an offset - it must come after the path |
1822 | $parent = substr $device, $parent - 4 * 3 - 4 * 4, 1e9, ""; |
1954 | $parent = substr $device, $parent - 4 * 3 - 4 * 4, 1e9, ""; |
1823 | ($parent, my $tail) = dec_device_ $parent; |
1955 | ($parent, my $tail) = dec_device_ $parent, $type; |
1824 | 0 == length $tail |
1956 | 0 == length $tail |
1825 | or die "trailing data after locate device parent\n"; |
1957 | or die "trailing data after locate device parent\n"; |
1826 | } else { |
1958 | } else { |
1827 | $parent = "null"; |
1959 | $parent = "null"; |
1828 | } |
1960 | } |
… | |
… | |
1834 | |
1966 | |
1835 | if ($mode == 0) { # "Element" |
1967 | if ($mode == 0) { # "Element" |
1836 | !length $path |
1968 | !length $path |
1837 | or die "device locate mode 0 having non-empty path ($mode, $elem, $path)\n"; |
1969 | or die "device locate mode 0 having non-empty path ($mode, $elem, $path)\n"; |
1838 | |
1970 | |
1839 | $elem = dec_bcde_id $elem; |
1971 | $elem = dec_bcde_id $elem, $type; |
1840 | $res .= "element,$elem"; |
1972 | $res .= "element,$elem"; |
1841 | |
1973 | |
1842 | } elsif ($mode == 1) { # "String" |
1974 | } elsif ($mode == 1) { # "String" |
1843 | !$elem |
1975 | !$elem |
1844 | or die "device locate mode 1 having non-zero element\n"; |
1976 | or die "device locate mode 1 having non-zero element\n"; |
… | |
… | |
1869 | |
2001 | |
1870 | ($res, $tail) |
2002 | ($res, $tail) |
1871 | } |
2003 | } |
1872 | |
2004 | |
1873 | # decode a full binary BCD device descriptor |
2005 | # decode a full binary BCD device descriptor |
1874 | sub dec_device($) { |
2006 | sub dec_device($$) { |
1875 | my ($device) = @_; |
2007 | my ($device, $type) = @_; |
1876 | |
2008 | |
1877 | $device = pack "H*", $device; |
2009 | $device = pack "H*", $device; |
1878 | |
2010 | |
1879 | my $guid = dec_guid substr $device, 0, 16, ""; |
2011 | my $guid = dec_guid substr $device, 0, 16, ""; |
1880 | $guid = $guid eq "00000000-0000-0000-0000-000000000000" |
2012 | $guid = $guid eq "00000000-0000-0000-0000-000000000000" |
1881 | ? "" : "{$guid}"; |
2013 | ? "" : "{$guid}"; |
1882 | |
2014 | |
1883 | eval { |
2015 | eval { |
1884 | my ($dev, $tail) = dec_device_ $device; |
2016 | my ($dev, $tail) = dec_device_ $device, $type; |
1885 | |
2017 | |
1886 | $tail eq "" |
2018 | $tail eq "" |
1887 | or die "unsupported trailing data after device descriptor\n"; |
2019 | or die "unsupported trailing data after device descriptor\n"; |
1888 | |
2020 | |
1889 | "$guid$dev" |
2021 | "$guid$dev" |
… | |
… | |
1901 | |
2033 | |
1902 | undef |
2034 | undef |
1903 | } |
2035 | } |
1904 | |
2036 | |
1905 | # encode the device portion after the GUID |
2037 | # encode the device portion after the GUID |
1906 | sub enc_device_; |
2038 | sub enc_device_($$); |
1907 | sub enc_device_ { |
2039 | sub enc_device_($$) { |
1908 | my ($device) = @_; |
2040 | my ($device, $type) = @_; |
1909 | |
2041 | |
1910 | my $enc_path = sub { |
2042 | my $enc_path = sub { |
1911 | my $path = shift; |
2043 | my $path = shift; |
1912 | $path =~ s/\//\\/g; |
2044 | $path =~ s/\//\\/g; |
1913 | (Encode::encode "UTF-16LE", $path) . "\x00\x00" |
2045 | (Encode::encode "UTF-16LE", $path) . "\x00\x00" |
… | |
… | |
1931 | |
2063 | |
1932 | my $parse_parent = sub { |
2064 | my $parse_parent = sub { |
1933 | my $parent; |
2065 | my $parent; |
1934 | |
2066 | |
1935 | if (s/^<//) { |
2067 | if (s/^<//) { |
1936 | ($parent, $_) = enc_device_ $_; |
2068 | ($parent, $_) = enc_device_ $_, $type; |
1937 | s/^>// |
2069 | s/^>// |
1938 | or die "$device: syntax error: parent device not followed by '>'\n"; |
2070 | or die "$device: syntax error: parent device not followed by '>'\n"; |
1939 | } else { |
2071 | } else { |
1940 | $parent = $NULL_DEVICE; |
2072 | $parent = $NULL_DEVICE; |
1941 | } |
2073 | } |
… | |
… | |
2029 | |
2161 | |
2030 | s/^,// |
2162 | s/^,// |
2031 | or die "$_: missing comma after locate parent device\n"; |
2163 | or die "$_: missing comma after locate parent device\n"; |
2032 | |
2164 | |
2033 | if (s/^element,//) { |
2165 | if (s/^element,//) { |
2034 | s/^([0-9a-z]+)//i |
2166 | s/^([0-9a-z:]+)//i |
2035 | or die "$_ locate element must be either name or 8-digit hex id\n"; |
2167 | or die "$_ locate element must be either name or 8-digit hex id\n"; |
2036 | $elem = enc_bcde_id $1; |
2168 | $elem = enc_bcde_id $1, $type; |
2037 | $mode = 0; |
2169 | $mode = 0; |
2038 | $path = $enc_path->(""); |
2170 | $path = $enc_path->(""); |
2039 | |
2171 | |
2040 | } elsif (s/^path,//) { |
2172 | } elsif (s/^path,//) { |
2041 | $mode = 1; |
2173 | $mode = 1; |
… | |
… | |
2120 | ); |
2252 | ); |
2121 | } |
2253 | } |
2122 | } |
2254 | } |
2123 | |
2255 | |
2124 | # encode a full binary BCD device descriptor |
2256 | # encode a full binary BCD device descriptor |
2125 | sub enc_device { |
2257 | sub enc_device($$) { |
2126 | my ($device) = @_; |
2258 | my ($device, $type) = @_; |
2127 | |
2259 | |
2128 | my $guid = "\x00" x 16; |
2260 | my $guid = "\x00" x 16; |
2129 | |
2261 | |
2130 | if ($device =~ s/^\{([A-Za-z0-9\-]+)\}//) { |
2262 | if ($device =~ s/^\{([A-Za-z0-9\-]+)\}//) { |
2131 | $guid = enc_guid $1 |
2263 | $guid = enc_guid $1 |
2132 | or die "$device: does not start with valid guid\n"; |
2264 | or die "$device: does not start with valid guid\n"; |
2133 | } |
2265 | } |
2134 | |
2266 | |
2135 | my ($descriptor, $tail) = enc_device_ $device; |
2267 | my ($descriptor, $tail) = enc_device_ $device, $type; |
2136 | |
2268 | |
2137 | length $tail |
2269 | length $tail |
2138 | and die "$device: garbage after device descriptor\n"; |
2270 | and die "$device: garbage after device descriptor\n"; |
2139 | |
2271 | |
2140 | unpack "H*", $guid . $descriptor |
2272 | unpack "H*", $guid . $descriptor |
… | |
… | |
2155 | $k = $bcd_objects{$k} // $k; |
2287 | $k = $bcd_objects{$k} // $k; |
2156 | |
2288 | |
2157 | my $type = $v->{Description}[0]{Type}[1]; |
2289 | my $type = $v->{Description}[0]{Type}[1]; |
2158 | |
2290 | |
2159 | if ($type != $bcd_object_types{$k}) { |
2291 | if ($type != $bcd_object_types{$k}) { |
2160 | $type = $bcd_types{$type} // sprintf "0x%08x", $type; |
2292 | $kv{type} = $bcd_types{$type} // sprintf "0x%08x", $type; |
2161 | $kv{type} = $type; |
|
|
2162 | } |
2293 | } |
2163 | |
2294 | |
2164 | my $elems = $v->{Elements}[1]; |
2295 | my $elems = $v->{Elements}[1]; |
2165 | |
2296 | |
2166 | while (my ($k, $v) = each %$elems) { |
2297 | while (my ($k, $v) = each %$elems) { |
2167 | my $k = hex $k; |
2298 | my $k = hex $k; |
2168 | |
2299 | |
2169 | my $v = $bcde_dec{$k & BCDE_FORMAT}->($v->[0]{Element}[1]); |
2300 | my $v = $bcde_dec{$k & BCDE_FORMAT}->($v->[0]{Element}[1], $type); |
2170 | my $k = dec_bcde_id $k; |
2301 | my $k = dec_bcde_id $k, $type; |
2171 | |
2302 | |
2172 | $kv{$k} = $v; |
2303 | $kv{$k} = $v; |
2173 | } |
2304 | } |
2174 | |
2305 | |
2175 | $bcd{$k} = \%kv; |
2306 | $bcd{$k} = \%kv; |
… | |
… | |
2216 | my %elem; |
2347 | my %elem; |
2217 | |
2348 | |
2218 | while (my ($k, $v) = each %$v) { |
2349 | while (my ($k, $v) = each %$v) { |
2219 | next if $k eq "type"; |
2350 | next if $k eq "type"; |
2220 | |
2351 | |
2221 | $k = (enc_bcde_id $k) // die "$k: invalid bcde element name or id\n"; |
2352 | $k = (enc_bcde_id $k, $type) // die "$k: invalid bcde element name or id\n"; |
2222 | $elem{sprintf "%08x", $k} = [{ |
2353 | $elem{sprintf "%08x", $k} = [{ |
2223 | Element => [ ($bcde_enc{$k & BCDE_FORMAT} // die "$k: unable to encode unknown bcd element type}")->($v)] |
2354 | Element => [ ($bcde_enc{$k & BCDE_FORMAT} // die "$k: unable to encode unknown bcd element type}")->($v)] |
2224 | }]; |
2355 | }]; |
2225 | } |
2356 | } |
2226 | |
2357 | |
… | |
… | |
2242 | Objects => [undef, \%objects], |
2373 | Objects => [undef, \%objects], |
2243 | }]] |
2374 | }]] |
2244 | } |
2375 | } |
2245 | |
2376 | |
2246 | ############################################################################# |
2377 | ############################################################################# |
|
|
2378 | # edit instructions |
2247 | |
2379 | |
2248 | sub bcd_edit_eval { |
2380 | sub bcd_edit_eval { |
2249 | package pbcdedit; |
2381 | package pbcdedit; |
2250 | |
2382 | |
2251 | our ($PATH, $BCD, $DEFAULT); |
2383 | our ($PATH, $BCD, $DEFAULT); |
… | |
… | |
2255 | } |
2387 | } |
2256 | |
2388 | |
2257 | sub bcd_edit { |
2389 | sub bcd_edit { |
2258 | my ($path, $bcd, @insns) = @_; |
2390 | my ($path, $bcd, @insns) = @_; |
2259 | |
2391 | |
2260 | my $default = $bcd->{"{bootmgr}"}{resumeobject}; |
2392 | my $default = $bcd->{"{bootmgr}"}{default}; |
2261 | |
2393 | |
2262 | # prepare "officially visible" variables |
2394 | # prepare "officially visible" variables |
2263 | local $pbcdedit::PATH = $path; |
2395 | local $pbcdedit::PATH = $path; |
2264 | local $pbcdedit::BCD = $bcd; |
2396 | local $pbcdedit::BCD = $bcd; |
2265 | local $pbcdedit::DEFAULT = $default; |
2397 | local $pbcdedit::DEFAULT = $default; |
… | |
… | |
2269 | |
2401 | |
2270 | if ($insn eq "get") { |
2402 | if ($insn eq "get") { |
2271 | my $object = shift @insns; |
2403 | my $object = shift @insns; |
2272 | my $elem = shift @insns; |
2404 | my $elem = shift @insns; |
2273 | |
2405 | |
2274 | $object = $default if $object eq "{default}"; |
2406 | $object = $object eq "{default}" ? $default : dec_wguid enc_wguid $object; |
2275 | |
2407 | |
2276 | print $bcd->{$object}{$elem}, "\n"; |
2408 | print $bcd->{$object}{$elem}, "\n"; |
2277 | |
2409 | |
2278 | } elsif ($insn eq "set") { |
2410 | } elsif ($insn eq "set") { |
2279 | my $object = shift @insns; |
2411 | my $object = shift @insns; |
2280 | my $elem = shift @insns; |
2412 | my $elem = shift @insns; |
2281 | my $value = shift @insns; |
2413 | my $value = shift @insns; |
2282 | |
2414 | |
2283 | $object = $default if $object eq "{default}"; |
2415 | $object = $object eq "{default}" ? $default : dec_wguid enc_wguid $object; |
2284 | |
2416 | |
2285 | $bcd->{$object}{$elem} = $value; |
2417 | $bcd->{$object}{$elem} = $value; |
2286 | |
2418 | |
2287 | } elsif ($insn eq "eval") { |
2419 | } elsif ($insn eq "eval") { |
2288 | bcd_edit_eval shift @insns; |
2420 | my $perl = shift @insns; |
|
|
2421 | bcd_edit_eval "#line 1 'eval'\n$perl"; |
2289 | |
2422 | |
2290 | } elsif ($insn eq "do") { |
2423 | } elsif ($insn eq "do") { |
2291 | my $path = shift @insns; |
2424 | my $path = shift @insns; |
2292 | my $file = file_load $path; |
2425 | my $file = file_load $path; |
2293 | bcd_edit_eval "#line 1 '$path'\n$file"; |
2426 | bcd_edit_eval "#line 1 '$path'\n$file"; |
… | |
… | |
2298 | } |
2431 | } |
2299 | |
2432 | |
2300 | } |
2433 | } |
2301 | |
2434 | |
2302 | ############################################################################# |
2435 | ############################################################################# |
|
|
2436 | # other utilities |
2303 | |
2437 | |
2304 | # json to stdout |
2438 | # json to stdout |
2305 | sub prjson($) { |
2439 | sub prjson($) { |
2306 | print $json_coder->encode ($_[0]); |
2440 | print $json_coder->encode ($_[0]); |
2307 | } |
2441 | } |
… | |
… | |
2311 | my $json; |
2445 | my $json; |
2312 | 1 while read STDIN, $json, 65536, length $json; |
2446 | 1 while read STDIN, $json, 65536, length $json; |
2313 | $json_coder->decode ($json) |
2447 | $json_coder->decode ($json) |
2314 | } |
2448 | } |
2315 | |
2449 | |
2316 | # all subcommands |
2450 | sub lsblk() { |
|
|
2451 | my $lsblk = $json_coder->decode (scalar qx<lsblk --json -o PATH,KNAME,MAJ:MIN,TYPE,PTTYPE,PTUUID,PARTUUID,LABEL,FSTYPE>); |
|
|
2452 | |
|
|
2453 | for my $dev (@{ $lsblk->{blockdevices} }) { |
|
|
2454 | if ($dev->{type} eq "part") { |
|
|
2455 | if ($dev->{pttype} eq "gpt") { |
|
|
2456 | $dev->{bcd_device} = "partition=<null>,harddisk,gpt,$dev->{ptuuid},$dev->{partuuid}"; |
|
|
2457 | } elsif ($dev->{pttype} eq "dos") { # why not "mbr" :( |
|
|
2458 | if ($dev->{partuuid} =~ /^([0-9a-f]{8})-([0-9a-f]{2})\z/i) { |
|
|
2459 | my ($diskid, $partno) = ($1, hex $2); |
|
|
2460 | $dev->{bcd_legacy_device} = "legacypartition=<null>,harddisk,mbr,$diskid,$partno"; |
|
|
2461 | if (open my $fh, "/sys/class/block/$dev->{kname}/start") { |
|
|
2462 | my $start = 512 * readline $fh; |
|
|
2463 | $dev->{bcd_device} = "partition=<null>,harddisk,mbr,$diskid,$start"; |
|
|
2464 | } |
|
|
2465 | } |
|
|
2466 | } |
|
|
2467 | } |
|
|
2468 | } |
|
|
2469 | |
|
|
2470 | $lsblk->{blockdevices} |
|
|
2471 | } |
|
|
2472 | |
|
|
2473 | sub prdev($$) { |
|
|
2474 | my ($path, $attribute) = @_; |
|
|
2475 | |
|
|
2476 | # rather than stat'ing and guessing how devices are encoded, we use lsblk for this |
|
|
2477 | # unfortunately, there doesn't seem to be a way to restrict lsblk to just oned evice, |
|
|
2478 | # so we always assume the first one is it. |
|
|
2479 | my $mm = $json_coder->decode (scalar qx<lsblk -o MAJ:MIN -J \Q$path\E>)->{blockdevices}[0]{"maj:min"}; |
|
|
2480 | |
|
|
2481 | my $lsblk = lsblk; |
|
|
2482 | |
|
|
2483 | for my $dev (@$lsblk) { |
|
|
2484 | if ($dev->{"maj:min"} eq $mm && $dev->{$attribute}) { |
|
|
2485 | say $dev->{$attribute}; |
|
|
2486 | exit 0; |
|
|
2487 | } |
|
|
2488 | } |
|
|
2489 | |
|
|
2490 | exit 1; |
|
|
2491 | } |
|
|
2492 | |
|
|
2493 | ############################################################################# |
|
|
2494 | # command line parser |
|
|
2495 | |
2317 | our %CMD = ( |
2496 | our %CMD = ( |
2318 | help => sub { |
2497 | help => sub { |
2319 | require Pod::Usage; |
2498 | require Pod::Usage; |
2320 | Pod::Usage::pod2usage (-verbose => 2); |
2499 | Pod::Usage::pod2usage (-verbose => 2); |
2321 | }, |
2500 | }, |
… | |
… | |
2346 | |
2525 | |
2347 | print "\n"; |
2526 | print "\n"; |
2348 | |
2527 | |
2349 | printf "%-39s %-23s %s\n", "Object GUID", "Alias", "(Hex) Default Type"; |
2528 | printf "%-39s %-23s %s\n", "Object GUID", "Alias", "(Hex) Default Type"; |
2350 | for my $name (sort keys %rbcd_objects) { |
2529 | for my $name (sort keys %rbcd_objects) { |
2351 | my $guid = $rbcd_objects{$name}; |
2530 | my $guid = $rbcd_objects{$name}; |
2352 | my $type = $bcd_object_types{$name}; |
2531 | my $type = $bcd_object_types{$name}; |
2353 | my $tname = $bcd_types{$type}; |
2532 | my $tname = $bcd_types{$type}; |
2354 | |
2533 | |
2355 | $type = $type ? sprintf "(%08x) %s", $type, $tname : "-"; |
2534 | $type = $type ? sprintf "(%08x) %s", $type, $tname : "-"; |
2356 | |
2535 | |
2357 | printf "%-39s %-23s %s\n", $guid, $name, $type; |
2536 | printf "%-39s %-23s %s\n", $guid, $name, $type; |
… | |
… | |
2371 | BCDE_FORMAT_GUID_LIST , "guid list", |
2550 | BCDE_FORMAT_GUID_LIST , "guid list", |
2372 | BCDE_FORMAT_INTEGER , "integer", |
2551 | BCDE_FORMAT_INTEGER , "integer", |
2373 | BCDE_FORMAT_BOOLEAN , "boolean", |
2552 | BCDE_FORMAT_BOOLEAN , "boolean", |
2374 | BCDE_FORMAT_INTEGER_LIST, "integer list", |
2553 | BCDE_FORMAT_INTEGER_LIST, "integer list", |
2375 | ); |
2554 | ); |
2376 | my %rbcde = reverse %bcde; |
|
|
2377 | $_ = sprintf "%08x", $_ for values %rbcde; |
|
|
2378 | |
2555 | |
2379 | my %element; |
2556 | my @element; |
2380 | |
2557 | |
|
|
2558 | for my $class (sort keys %rbcde_byclass) { |
|
|
2559 | my $rbcde = $rbcde_byclass{$class}; |
|
|
2560 | |
2381 | unless ($json) { |
2561 | unless ($json) { |
2382 | print "\n"; |
2562 | print "\n"; |
|
|
2563 | printf "Elements applicable to class(es): $class\n"; |
2383 | printf "%-9s %-12s %s\n", "Element", "Format", "Name Alias"; |
2564 | printf "%-9s %-12s %s\n", "Element", "Format", "Name Alias"; |
2384 | } |
2565 | } |
2385 | for my $name (sort keys %rbcde) { |
2566 | for my $name (sort keys %$rbcde) { |
2386 | my $id = $rbcde{$name}; |
2567 | my $id = $rbcde->{$name}; |
2387 | my $format = $format_name{(hex $id) & BCDE_FORMAT}; |
2568 | my $format = $format_name{$id & BCDE_FORMAT}; |
2388 | |
2569 | |
2389 | if ($json) { |
2570 | if ($json) { |
2390 | $element{$id} = [$format, $name]; |
2571 | push @element, [$class, $id * 1, $format, $name]; |
2391 | } else { |
2572 | } else { |
|
|
2573 | $id = sprintf "%08x", $id; |
2392 | printf "%-9s %-12s %s\n", $id, $format, $name; |
2574 | printf "%-9s %-12s %s\n", $id, $format, $name; |
|
|
2575 | } |
2393 | } |
2576 | } |
2394 | } |
2577 | } |
2395 | print "\n" unless $json; |
2578 | print "\n" unless $json; |
2396 | |
2579 | |
2397 | prjson { |
2580 | prjson { |
2398 | version => $JSON_VERSION, |
2581 | version => $JSON_VERSION, |
2399 | element => \%element, |
2582 | element => \@element, |
|
|
2583 | class => \@bcde_typeclass, |
2400 | } if $json; |
2584 | } if $json; |
2401 | |
2585 | |
2402 | }, |
2586 | }, |
2403 | |
2587 | |
2404 | export => sub { |
2588 | export => sub { |
… | |
… | |
2430 | "import-regf" => sub { |
2614 | "import-regf" => sub { |
2431 | regf_save shift, rdjson; |
2615 | regf_save shift, rdjson; |
2432 | }, |
2616 | }, |
2433 | |
2617 | |
2434 | lsblk => sub { |
2618 | lsblk => sub { |
|
|
2619 | my $json = $_[0] eq "--json"; |
|
|
2620 | |
|
|
2621 | my $lsblk = lsblk; |
|
|
2622 | |
|
|
2623 | if ($json) { |
|
|
2624 | prjson $lsblk; |
|
|
2625 | } else { |
2435 | printf "%-10s %-8.8s %-6.6s %-3s %s\n", "DEVICE", "LABEL", "FSTYPE", "PT", "DEVICE DESCRIPTOR"; |
2626 | printf "%-10s %-8.8s %-6.6s %-3s %s\n", "DEVICE", "LABEL", "FSTYPE", "PT", "DEVICE DESCRIPTOR"; |
2436 | |
2627 | for my $dev (@$lsblk) { |
2437 | my $lsblk = $json_coder->decode (scalar qx<lsblk --json -o PATH,KNAME,TYPE,PTTYPE,PTUUID,PARTUUID,LABEL,FSTYPE>); |
2628 | for my $bcd ($dev->{bcd_device}, $dev->{bcd_legacy_device}) { |
2438 | |
|
|
2439 | for my $dev (@{ $lsblk->{blockdevices} }) { |
|
|
2440 | my $pr = sub { |
|
|
2441 | printf "%-10s %-8.8s %-6.6s %-3s %s\n", |
2629 | printf "%-10s %-8.8s %-6.6s %-3s %s\n", |
2442 | $dev->{path}, $dev->{label}, $dev->{fstype}, $dev->{pttype}, $_[0]; |
2630 | $dev->{path}, $dev->{label}, $dev->{fstype}, $dev->{pttype}, $bcd |
2443 | }; |
|
|
2444 | |
|
|
2445 | if ($dev->{type} eq "part") { |
|
|
2446 | if ($dev->{pttype} eq "gpt") { |
|
|
2447 | $pr->("partition=<null>,harddisk,gpt,$dev->{ptuuid},$dev->{partuuid}"); |
|
|
2448 | } elsif ($dev->{pttype} eq "dos") { # why not "mbr" :( |
|
|
2449 | if ($dev->{partuuid} =~ /^([0-9a-f]{8})-([0-9a-f]{2})\z/i) { |
|
|
2450 | my ($diskid, $partno) = ($1, hex $2); |
|
|
2451 | $pr->("legacypartition=<null>,harddisk,mbr,$diskid,$partno"); |
|
|
2452 | if (open my $fh, "/sys/class/block/$dev->{kname}/start") { |
|
|
2453 | my $start = 512 * readline $fh; |
|
|
2454 | $pr->("partition=<null>,harddisk,mbr,$diskid,$start"); |
|
|
2455 | } |
2631 | if $bcd; |
2456 | } |
|
|
2457 | } |
2632 | } |
2458 | } |
2633 | } |
2459 | } |
2634 | } |
2460 | }, |
2635 | }, |
|
|
2636 | |
|
|
2637 | "bcd-device" => sub { |
|
|
2638 | prdev shift, "bcd_device"; |
|
|
2639 | }, |
|
|
2640 | |
|
|
2641 | "bcd-legacy-device" => sub { |
|
|
2642 | prdev shift, "bcd_legacy_device"; |
|
|
2643 | }, |
|
|
2644 | |
|
|
2645 | version => sub { |
|
|
2646 | print "\n", |
|
|
2647 | "PBCDEDIT version $VERSION, copyright 2019 Marc A. Lehmann <pbcdedit\@schmorp.de>.\n", |
|
|
2648 | "JSON schema version: $JSON_VERSION\n", |
|
|
2649 | "Licensed under the GNU General Public License Version 3.0, or any later version.\n", |
|
|
2650 | "\n", |
|
|
2651 | $CHANGELOG, |
|
|
2652 | "\n"; |
|
|
2653 | }, |
2461 | ); |
2654 | ); |
2462 | |
2655 | |
2463 | my $cmd = shift; |
2656 | my $cmd = shift; |
2464 | |
2657 | |
2465 | unless (exists $CMD{$cmd}) { |
2658 | unless (exists $CMD{$cmd}) { |