1 /* SPDX-License-Identifier: GPL-2.0-only */
15 #include <commonlib/helpers.h>
21 #define DEF_ALLOC 1024
31 } __attribute__ ((packed
)) optionrom_header_t
;
46 } __attribute__((packed
)) optionrom_pcir_t
;
57 } __attribute__ ((packed
));
67 u8 type
; /* 0 == desktop, 1 == mobile */
72 u8 rsvd2
:6; /* finish byte */
79 u8 rsvd4
; /* popup memory size */
81 u8 rsvd5
; /* is crt already on ddc2 */
82 } __attribute__ ((packed
));
84 struct bdb_general_features
{
93 u8 download_ext_vbt
:1;
96 u8 enable_lfp_on_override
:1;
99 u8 display_clock_mode
:1;
100 u8 rsvd8
:1; /* finish byte */
103 u8 disable_smooth_vision
:1;
106 u8 fdi_rx_polarity_inverted
:1;
107 u8 rsvd10
:4; /* finish byte */
110 u8 legacy_monitor_detect
;
113 u8 int_crt_support
:1;
115 u8 int_efp_support
:1;
116 u8 dp_ssc_enb
:1; /* PCH attached eDP supports SSC */
117 u8 dp_ssc_freq
:1; /* SSC freq for PCH attached eDP */
118 u8 rsvd11
:3; /* finish byte */
119 } __attribute__ ((packed
));
121 struct common_child_dev_config
{
133 } __attribute__ ((packed
));
135 struct bdb_general_definitions
{
137 u8 crt_ddc_gmbus_pin
;
141 u8 skip_boot_crt_detect
:1;
143 u8 rsvd1
:5; /* finish byte */
145 /* boot device bits */
151 * If TV is present, it'll be at devices[0].
152 * LVDS will be next, either devices[0] or [1], if present.
153 * On some platforms the number of device is 6. But could be as few as
154 * 4 if both TV and LVDS are missing.
155 * And the device num is related with the size of general definition
156 * block. It is obtained by using the following formula:
157 * number = (block_size - sizeof(bdb_general_definitions))/
158 * sizeof(child_device_config);
160 struct common_child_dev_config devices
[0];
161 } __attribute__ ((packed
));
163 struct bdb_driver_features
{
164 u8 boot_dev_algorithm
:1;
165 u8 block_display_switch
:1;
166 u8 allow_display_switch
:1;
170 u8 sprite_in_clone
:1;
176 u8 boot_mode_refresh
;
178 u16 enable_lfp_primary
:1;
179 u16 selective_mode_pruning
:1;
180 u16 dual_frequency
:1;
181 u16 render_clock_freq
:1; /* 0: high freq; 1: low freq */
182 u16 nt_clone_support
:1;
183 u16 power_scheme_ui
:1; /* 0: CUI; 1: 3rd party */
184 u16 sprite_display_assign
:1; /* 0: secondary; 1: primary */
185 u16 cui_aspect_scaling
:1;
186 u16 preserve_aspect_ratio
:1;
187 u16 sdvo_device_power_down
:1;
195 u16 legacy_crt_max_x
;
196 u16 legacy_crt_max_y
;
197 u8 legacy_crt_max_refresh
;
200 u8 custom_vbt_version
;
201 } __attribute__ ((packed
));
203 struct bdb_lvds_options
{
206 /* LVDS capabilities, stored in a dword */
208 u8 pfit_text_mode_enhanced
:1;
209 u8 pfit_gfx_mode_enhanced
:1;
210 u8 pfit_ratio_auto
:1;
215 } __attribute__ ((packed
));
217 struct bdb_sdvo_lvds_options
{
219 u8 h40_set_panel_type
;
224 u8 sclalarcoeff_tab_row_num
;
225 u8 sclalarcoeff_tab_row_size
;
227 u8 panel_misc_bits_1
;
228 u8 panel_misc_bits_2
;
229 u8 panel_misc_bits_3
;
230 u8 panel_misc_bits_4
;
231 } __attribute__ ((packed
));
234 static const size_t ignore_checksum
= 1;
236 #define BDB_GENERAL_FEATURES 1
237 #define BDB_GENERAL_DEFINITIONS 2
239 #define BDB_DRIVER_FEATURES 12
240 #define BDB_SDVO_LVDS_OPTIONS 22
241 #define BDB_SDVO_PANEL_DTDS 23
242 #define BDB_LVDS_OPTIONS 40
243 #define BDB_LVDS_LFP_DATA_PTRS 41
244 #define BDB_LVDS_LFP_DATA 42
249 static void print(const char *format
, ...)
252 fprintf(stdout
, "VBTTOOL: ");
253 va_start(args
, format
);
254 vfprintf(stdout
, format
, args
);
258 static void printt(const char *format
, ...)
261 fprintf(stdout
, "\t");
262 va_start(args
, format
);
263 vfprintf(stdout
, format
, args
);
267 static void printwarn(const char *format
, ...)
270 fprintf(stderr
, "VBTTOOL: WARN: ");
271 va_start(args
, format
);
272 vfprintf(stderr
, format
, args
);
276 static void printerr(const char *format
, ...)
279 fprintf(stderr
, "VBTTOOL: ERR: ");
280 va_start(args
, format
);
281 vfprintf(stderr
, format
, args
);
290 /* file object helpers */
293 * Alloc a file object of given size.
294 * Returns NULL on error.
296 static struct fileobject
*malloc_fo(const size_t size
)
298 struct fileobject
*fo
;
302 fo
= malloc(sizeof(*fo
));
305 fo
->data
= malloc(size
);
315 /* Free a fileobject structure */
316 static void free_fo(struct fileobject
*fo
)
324 /* Resize file object and keep memory content */
325 static struct fileobject
*remalloc_fo(struct fileobject
*old
,
328 struct fileobject
*fo
= old
;
333 fo
->data
= realloc(fo
->data
, size
);
338 memset(&fo
->data
[fo
->size
], 0, size
- fo
->size
);
346 * Creates a new subregion copy of fileobject.
347 * Returns NULL if offset is greater than fileobject size.
348 * Returns NULL on error.
350 static struct fileobject
*malloc_fo_sub(const struct fileobject
*old
,
353 struct fileobject
*fo
;
355 if (!old
|| off
> old
->size
)
358 fo
= malloc_fo(old
->size
- off
);
362 memcpy(fo
->data
, old
->data
+ off
, fo
->size
);
369 /* Create fileobject from file */
370 static struct fileobject
*read_file(const char *filename
)
372 FILE *fd
= fopen(filename
, "rb");
373 off_t read_size
= DEF_ALLOC
;
376 printerr("%s open failed: %s\n", filename
, strerror(errno
));
380 struct fileobject
*fo
= malloc_fo(read_size
);
382 printerr("malloc failed\n");
387 off_t total_bytes_read
= 0, bytes_read
;
388 while ((bytes_read
= fread(fo
->data
+ total_bytes_read
, 1, read_size
, fd
)) > 0) {
389 total_bytes_read
+= bytes_read
;
390 struct fileobject
*newfo
= remalloc_fo(fo
, fo
->size
+ read_size
);
399 if (!total_bytes_read
) {
406 printerr("%s close failed: %s\n", filename
, strerror(errno
));
411 fo
->size
= total_bytes_read
;
416 /* Create fileobject from physical memory at given address of size 64 KiB */
417 static struct fileobject
*read_physmem(size_t addr
)
419 const int fd
= open("/dev/mem", O_RDONLY
);
420 const size_t size
= 64 * 2 * KiB
;
422 printerr("/dev/mem open failed: %s\n", strerror(errno
));
426 const void *data
= mmap(0, size
, PROT_READ
, MAP_SHARED
, fd
, addr
);
427 if (data
== MAP_FAILED
) {
429 printerr("mmap failed: %s\n", strerror(errno
));
433 struct fileobject
*fo
= malloc_fo(size
);
435 printerr("malloc failed\n");
436 munmap((void *)data
, size
);
441 memcpy(fo
->data
, data
, size
);
442 munmap((void *)data
, size
);
445 printerr("/dev/mem close failed: %s\n", strerror(errno
));
453 /* Write fileobject contents to file */
454 static int write_file(const char *filename
, const struct fileobject
*fo
)
456 FILE *fd_out
= fopen(filename
, "wb");
459 printerr("%s open failed: %s\n", filename
, strerror(errno
));
462 if (fwrite(fo
->data
, 1, fo
->size
, fd_out
) != fo
->size
) {
466 return fclose(fd_out
);
469 /* dump VBT contents in human readable form */
470 static void dump_vbt(const struct fileobject
*fo
)
472 if (fo
->size
< sizeof(struct vbt_header
))
475 const struct vbt_header
*head
= (const struct vbt_header
*)fo
->data
;
476 const struct bdb_header
*bdb
;
479 int is_first_skip
= 1;
481 printt("signature: <%20.20s>\n", head
->signature
);
482 printt("version: %d.%02d\n", head
->version
/ 100,
483 head
->version
% 100);
484 if (head
->header_size
!= sizeof(struct vbt_header
))
485 printt("header size: 0x%x\n", head
->header_size
);
486 printt("VBT size: 0x%x\n", head
->vbt_size
);
487 printt("VBT checksum: 0x%x\n", head
->vbt_checksum
);
489 printt("header reserved0: 0x%x\n", head
->reserved0
);
490 if (head
->bdb_offset
!= sizeof(struct vbt_header
))
491 printt("BDB offset: 0x%x\n", head
->bdb_offset
);
493 for (i
= 0; i
< 4; i
++)
494 if (head
->aim_offset
[i
])
495 printt("AIM[%d] offset: 0x%x\n", i
,
496 head
->aim_offset
[i
]);
497 if (head
->bdb_offset
+ sizeof(*bdb
) > fo
->size
)
499 bdb
= (const void *) (fo
->data
+ head
->bdb_offset
);
501 if (memcmp("BIOS_DATA_BLOCK ", bdb
->signature
, 16) != 0) {
502 printerr("invalid BDB signature:%s\n",
506 printt("BDB version: %d.%02d\n", bdb
->version
/ 100,
508 if (bdb
->header_size
!= sizeof(struct bdb_header
))
509 printt("BDB header size: 0x%x\n", bdb
->header_size
);
510 if (bdb
->bdb_size
!= head
->vbt_size
- head
->bdb_offset
)
511 printt("BDB size: 0x%x\n", bdb
->bdb_size
);
512 for (ptr
= (const u8
*) bdb
+ bdb
->header_size
;
513 ptr
< (const u8
*) bdb
+ bdb
->bdb_size
;) {
514 u16 secsz
= (ptr
[1] | (ptr
[2] << 8));
516 const u8
*section
= ptr
+ 3;
518 printt("section type %d, size 0x%x\n", sectype
, secsz
);
521 case BDB_GENERAL_FEATURES
:{
522 const struct bdb_general_features
*sec
=
523 (const void *) section
;
524 printt("General features:\n");
526 if (sec
->panel_fitting
)
527 printt("\tpanel_fitting = 0x%x\n",
530 printt("\tflexaim = 0x%x\n",
533 printt("\tmsg_enable = 0x%x\n",
535 if (sec
->clear_screen
)
536 printt("\tclear_screen = 0x%x\n",
539 printt("\tcolor_flip = 0x%x\n",
541 if (sec
->download_ext_vbt
)
543 ("\tdownload_ext_vbt = 0x%x\n",
544 sec
->download_ext_vbt
);
545 printt("\t*enable_ssc = 0x%x\n",
547 printt("\t*ssc_freq = 0x%x\n",
549 if (sec
->enable_lfp_on_override
)
551 ("\tenable_lfp_on_override = 0x%x\n",
552 sec
->enable_lfp_on_override
);
553 if (sec
->disable_ssc_ddt
)
555 ("\tdisable_ssc_ddt = 0x%x\n",
556 sec
->disable_ssc_ddt
);
558 printt("\trsvd7 = 0x%x\n",
560 printt("\t*display_clock_mode = 0x%x\n",
561 sec
->display_clock_mode
);
563 printt("\trsvd8 = 0x%x\n",
565 printt("\tdisable_smooth_vision = 0x%x\n",
566 sec
->disable_smooth_vision
);
568 printt("\tsingle_dvi = 0x%x\n",
571 printt("\trsvd9 = 0x%x\n",
574 ("\t*fdi_rx_polarity_inverted = 0x%x\n",
575 sec
->fdi_rx_polarity_inverted
);
577 printt("\trsvd10 = 0x%x\n",
579 if (sec
->legacy_monitor_detect
)
581 ("\tlegacy_monitor_detect = 0x%x\n",
582 sec
->legacy_monitor_detect
);
583 printt("\t*int_crt_support = 0x%x\n",
584 sec
->int_crt_support
);
585 printt("\t*int_tv_support = 0x%x\n",
586 sec
->int_tv_support
);
587 if (sec
->int_efp_support
)
589 ("\tint_efp_support = 0x%x\n",
590 sec
->int_efp_support
);
592 printt("\tdp_ssc_enb = 0x%x\n",
594 if (sec
->dp_ssc_freq
)
595 printt("\tdp_ssc_freq = 0x%x\n",
598 printt("\trsvd11 = 0x%x\n",
602 case BDB_DRIVER_FEATURES
:{
603 const struct bdb_driver_features
*sec
=
604 (const void *) section
;
605 printt("\t*LVDS config: %d\n",
607 printt("\t*Dual frequency: %d\n",
608 sec
->dual_frequency
);
612 case BDB_SDVO_LVDS_OPTIONS
:{
613 const struct bdb_sdvo_lvds_options
*sec
=
614 (const void *) section
;
615 printt("\t*Panel type: %d\n",
620 case BDB_GENERAL_DEFINITIONS
:{
621 const struct bdb_general_definitions
*sec
=
622 (const void *) section
;
624 printt("\t*CRT DDC GMBUS pin: %d\n",
625 sec
->crt_ddc_gmbus_pin
);
627 printt("\tDPMS ACPI: %d\n",
629 printt("\tSkip boot CRT detect: %d\n",
630 sec
->skip_boot_crt_detect
);
631 printt("\tDPMS aim: %d\n", sec
->dpms_aim
);
633 printt("\trsvd1: 0x%x\n",
635 printt("\tboot_display: { %x, %x }\n",
636 sec
->boot_display
[0],
637 sec
->boot_display
[1]);
638 if (sec
->child_dev_size
!=
639 sizeof(struct common_child_dev_config
))
640 printt("\tchild_dev_size: %d\n",
641 sec
->child_dev_size
);
642 ndev
= (secsz
- sizeof(*sec
)) /
643 sizeof(struct common_child_dev_config
);
644 printt("\t%d devices\n", ndev
);
645 for (i
= 0; i
< ndev
; i
++) {
646 printt("\t*device type: %x ",
649 #define DEVICE_TYPE_INT_LFP 0x1022
650 #define DEVICE_TYPE_INT_TV 0x1009
651 #define DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR 0x6052
652 switch (sec
->devices
[i
].device_type
) {
653 case DEVICE_TYPE_INT_LFP
:
654 printt("(flat panel)\n");
656 case DEVICE_TYPE_INT_TV
:
659 case DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR
:
667 printt("(Unknown)\n");
670 if (!sec
->devices
[i
].device_type
)
672 printt("\t *dvo_port: %x\n",
673 sec
->devices
[i
].dvo_port
);
674 printt("\t *i2c_pin: %x\n",
675 sec
->devices
[i
].i2c_pin
);
676 printt("\t *slave_addr: %x\n",
677 sec
->devices
[i
].slave_addr
);
678 printt("\t *ddc_pin: %x\n",
679 sec
->devices
[i
].ddc_pin
);
680 printt("\t *dvo_wiring: %x\n",
681 sec
->devices
[i
].dvo_wiring
);
682 printt("\t edid_ptr: %x\n",
683 sec
->devices
[i
].edid_ptr
);
689 const struct vbios_data
*sec
=
690 (const void *) section
;
694 printt("\ttype: %x\n", sec
->type
);
695 printt("\trelstage: %x\n", sec
->relstage
);
696 printt("\tchipset: %x\n", sec
->chipset
);
697 printt(sec
->lvds_present
? "\tLVDS\n"
699 printt(sec
->tv_present
? "\tTV\n"
702 printt("\trsvd2: 0x%x\n",
704 for (i
= 0; i
< 4; i
++)
707 ("\trsvd3[%d]: 0x%x\n",
709 printt("\tSignon: %.155s\n", sec
->signon
);
710 printt("\tCopyright: %.155s\n",
712 printt("\tCode segment: %x\n",
714 printt("\tDOS Boot mode: %x\n",
716 printt("\tBandwidth percent: %x\n",
717 sec
->bandwidth_percent
);
719 printt("\trsvd4: 0x%x\n",
721 printt("\tBandwidth percent: %x\n",
722 sec
->resize_pci_bios
);
724 printt("\trsvd5: 0x%x\n",
732 /* Returns a new fileobject containing a valid VBT */
733 static void parse_vbt(const struct fileobject
*fo
,
734 struct fileobject
**vbt
)
738 if (fo
->size
< sizeof(struct vbt_header
)) {
739 printerr("image is too small\n");
743 const struct vbt_header
*head
=
744 (const struct vbt_header
*)fo
->data
;
746 if (memcmp(head
->signature
, "$VBT", 4) != 0) {
747 printerr("invalid VBT signature\n");
751 if (!head
->vbt_size
|| head
->vbt_size
> fo
->size
) {
752 printerr("invalid VBT size\n");
756 if (!head
->bdb_offset
||
757 head
->bdb_offset
> fo
->size
- sizeof(struct bdb_header
)) {
758 printerr("invalid BDB offset\n");
762 if (!head
->header_size
|| head
->header_size
> fo
->size
) {
763 printerr("invalid header size\n");
767 const struct bdb_header
*const bdb_head
=
768 (const struct bdb_header
*)((const u8
*)head
+ head
->bdb_offset
);
769 if (memcmp(bdb_head
->signature
, "BIOS_DATA_BLOCK ", 16) != 0) {
770 printerr("invalid BDB signature\n");
774 if (!bdb_head
->header_size
|| bdb_head
->header_size
> fo
->size
) {
775 printerr("invalid BDB header size\n");
779 /* Duplicate fo as caller is owner and remalloc frees the object */
780 struct fileobject
*dupfo
= malloc_fo_sub(fo
, 0);
782 printerr("malloc failed\n");
786 struct fileobject
*newfo
= remalloc_fo(dupfo
, head
->vbt_size
);
788 printerr("remalloc failed\n");
796 /* Option ROM checksum */
797 static u8
checksum_vbios(const optionrom_header_t
*oh
)
799 const u8
*ptr
= (const u8
*)oh
;
803 for (i
= 0; i
< ((MIN(oh
->size
, 128)) * 512); i
++)
809 /* Verify Option ROM contents */
810 static int is_valid_vbios(const struct fileobject
*fo
)
812 if (fo
->size
> 64 * 2 * KiB
) {
813 printerr("VBIOS is too big\n");
817 if (fo
->size
< sizeof(optionrom_header_t
)) {
818 printerr("VBIOS is too small\n");
822 const optionrom_header_t
*oh
= (const optionrom_header_t
*)fo
->data
;
824 if (oh
->signature
!= 0xaa55) {
825 printerr("bad oprom signature: 0x%x\n", oh
->signature
);
829 if (oh
->size
== 0 || oh
->size
> 0x80 || oh
->size
* 512 > fo
->size
) {
830 printerr("bad oprom size: 0x%x\n", oh
->size
);
834 const u8 cksum
= checksum_vbios(oh
);
836 if (!ignore_checksum
) {
837 printerr("bad oprom checksum: 0x%x\n", cksum
);
840 printwarn("bad oprom checksum: 0x%x\n", cksum
);
843 if (oh
->pcir_offset
+ sizeof(optionrom_pcir_t
) > fo
->size
) {
844 printerr("bad pcir offset: 0x%x\n", oh
->pcir_offset
);
848 if (oh
->pcir_offset
) {
849 const optionrom_pcir_t
*pcir
;
850 pcir
= (const optionrom_pcir_t
*)
851 ((const u8
*)oh
+ oh
->pcir_offset
);
853 if (pcir
->signature
!= 0x52494350) {
854 printerr("Invalid PCIR signature\n");
858 if (pcir
->vendor
!= 0x8086) {
859 printerr("Not an Intel VBIOS\n");
863 if (pcir
->classcode
[0] != 0 || pcir
->classcode
[1] != 0 ||
864 pcir
->classcode
[2] != 3) {
865 printerr("Not a VGA Option Rom\n");
869 printwarn("no PCIR header found\n");
876 * Parse Option ROM and return a valid VBT fileobject.
877 * Caller has to make sure that it is a valid VBIOS.
878 * Return a NULL fileobject on error.
880 static void parse_vbios(const struct fileobject
*fo
,
881 struct fileobject
**vbt
)
883 const optionrom_header_t
*oh
= (const optionrom_header_t
*)fo
->data
;
888 if (!oh
->vbt_offset
) {
889 printerr("no VBT found\n");
893 if (oh
->vbt_offset
> (fo
->size
- sizeof(struct vbt_header
))) {
894 printerr("invalid VBT offset\n");
898 struct fileobject
*fo_vbt
= malloc_fo_sub(fo
, oh
->vbt_offset
);
900 parse_vbt(fo_vbt
, vbt
);
905 printwarn("VBT wasn't found at specified offset of %04x\n",
908 for (i
= sizeof(optionrom_header_t
);
909 i
<= fo
->size
- sizeof(struct vbt_header
); i
++) {
910 struct fileobject
*fo_vbt
= malloc_fo_sub(fo
, i
);
914 parse_vbt(fo_vbt
, vbt
);
923 /* Short VBT summary in human readable form */
924 static void print_vbt(const struct fileobject
*fo
)
926 const struct bdb_header
*bdb
;
928 if (fo
->size
< sizeof(struct vbt_header
))
931 const struct vbt_header
*head
= (const struct vbt_header
*)fo
->data
;
933 print("Found VBT:\n");
934 printt("signature: <%20.20s>\n", head
->signature
);
935 printt("version: %d.%02d\n", head
->version
/ 100, head
->version
% 100);
936 if (head
->header_size
!= sizeof(struct vbt_header
))
937 printt("header size: 0x%x\n", head
->header_size
);
938 printt("VBT size: 0x%x\n", head
->vbt_size
);
939 printt("VBT checksum: 0x%x\n", head
->vbt_checksum
);
941 if (head
->bdb_offset
> (fo
->size
- sizeof(struct bdb_header
))) {
942 printerr("invalid BDB offset\n");
945 bdb
= (const struct bdb_header
*)
946 ((const char *)head
+ head
->bdb_offset
);
948 if (memcmp("BIOS_DATA_BLOCK ", bdb
->signature
, 16) != 0) {
949 printerr("invalid BDB signature:%s\n", bdb
->signature
);
952 printt("BDB version: %u.%02u\n", bdb
->version
/ 100,
956 static void print_usage(const char *argv0
, struct option
*long_options
)
959 printf("\nUsage:\n");
960 printf("%s --<SOURCECMD> [filename] --<DESTCMD> [filename]\n\n", argv0
);
961 printf("SOURCECMD set the VBT source. Supported:\n");
962 printf(" %-10s: Legacy BIOS area at phys. memory 0xc0000\n",
964 printf(" %-10s: Read raw Intel VBT file\n", "invbt");
965 printf(" %-10s: Read VBT from Intel Option ROM file\n\n", "inoprom");
966 printf("DESTCMD set the VBT destination. Supported:\n");
967 printf(" %-10s: Print VBT in human readable form\n", "outdump");
968 printf(" %-10s: Write raw Intel VBT file\n", "outvbt");
969 printf(" %-10s: Patch existing Intel Option ROM\n\n", "patchoprom");
971 printf("Supported arguments:\n");
972 while (long_options
[i
].name
) {
973 printf("\t-%c --%s %s\n", long_options
[i
].val
,
974 long_options
[i
].name
, long_options
[i
].has_arg
?
980 /* Fix VBIOS header and PCIR */
981 static int fix_vbios_header(struct fileobject
*fo
)
983 if (!fo
|| fo
->size
< sizeof(optionrom_header_t
))
986 optionrom_header_t
*oh
= (optionrom_header_t
*)fo
->data
;
988 /* Fix size alignment */
989 if (fo
->size
% 512) {
990 print("Aligning size to 512\n");
991 fo
= remalloc_fo(fo
, (fo
->size
+ 511) / 512 * 512);
994 oh
= (optionrom_header_t
*)fo
->data
;
998 oh
->size
= fo
->size
/ 512;
1000 /* Fix checksum field */
1001 oh
->checksum
= -(checksum_vbios(oh
) - oh
->checksum
);
1006 /* Return the VBT structure size in bytes */
1007 static size_t vbt_size(const struct fileobject
*fo
)
1009 if (!fo
|| fo
->size
< sizeof(struct vbt_header
))
1011 const struct vbt_header
*head
= (const struct vbt_header
*)fo
->data
;
1013 return head
->vbt_size
;
1017 * Patch an Intel Option ROM with new VBT.
1018 * Caller has to make sure that VBIOS and VBT are valid.
1019 * Return 1 on error.
1021 static int patch_vbios(struct fileobject
*fo
,
1022 const struct fileobject
*fo_vbt
)
1024 optionrom_header_t
*oh
= (optionrom_header_t
*)fo
->data
;
1025 struct vbt_header
*head
;
1027 struct fileobject
*old_vbt
= NULL
;
1028 parse_vbios(fo
, &old_vbt
);
1031 if (oh
->vbt_offset
+ vbt_size(old_vbt
) == fo
->size
) {
1032 /* Located at the end of file - reduce file size */
1033 if (fo
->size
< vbt_size(old_vbt
)) {
1037 fo
= remalloc_fo(fo
, fo
->size
- vbt_size(old_vbt
));
1039 printerr("Failed to allocate memory\n");
1043 oh
= (optionrom_header_t
*)fo
->data
;
1045 } else if (vbt_size(old_vbt
) < vbt_size(fo_vbt
)) {
1046 /* In the middle of the file - Remove old VBT */
1047 memset(fo
->data
+ oh
->vbt_offset
, 0xff,
1051 /* New VBT overwrites existing one - Clear memory */
1052 memset(fo
->data
+ oh
->vbt_offset
, 0xff,
1059 if (!oh
->vbt_offset
) {
1060 print("increasing VBIOS to append VBT\n");
1061 if ((fo
->size
+ vbt_size(fo_vbt
)) >= 2 * 64 * KiB
) {
1062 printerr("VBT won't fit\n");
1066 oh
->vbt_offset
= fo
->size
;
1067 fo
= remalloc_fo(fo
, fo
->size
+ vbt_size(fo_vbt
));
1069 printerr("Failed to allocate memory\n");
1072 oh
= (optionrom_header_t
*)fo
->data
;
1075 head
= (struct vbt_header
*)((u8
*)oh
+ oh
->vbt_offset
);
1076 memcpy(head
, fo_vbt
->data
, vbt_size(fo_vbt
));
1081 int main(int argc
, char **argv
)
1083 int opt
, ret
, option_index
= 0;
1085 size_t has_input
= 0, has_output
= 0;
1086 size_t dump
= 0, in_legacy
= 0;
1087 char *in_vbt
= NULL
, *in_oprom
= NULL
;
1088 char *out_vbt
= NULL
, *patch_oprom
= NULL
;
1089 static struct option long_options
[] = {
1090 {"help", 0, 0, 'h'},
1091 {"outdump", 0, 0, 'd'},
1092 {"inlegacy", 0, 0, 'l'},
1093 {"invbt", required_argument
, 0, 'f'},
1094 {"inoprom", required_argument
, 0, 'o'},
1095 {"outvbt", required_argument
, 0, 'v'},
1096 {"patchoprom", required_argument
, 0, 'p'},
1100 while ((opt
= getopt_long(argc
, argv
, "hdlf:o:v:p:i",
1101 long_options
, &option_index
)) != EOF
) {
1112 in_vbt
= strdup(optarg
);
1116 in_oprom
= strdup(optarg
);
1120 out_vbt
= strdup(optarg
);
1124 patch_oprom
= strdup(optarg
);
1129 print_usage(argv
[0], long_options
);
1136 printerr("No input specified !\n");
1138 printerr("No output specified !\n");
1139 if (argc
< 2 || argc
> 6 || !has_input
|| !has_output
) {
1140 print_usage(argv
[0], long_options
);
1144 struct fileobject
*fo
;
1147 fo
= read_physmem(0xc0000);
1149 fo
= read_file(in_vbt
);
1151 fo
= read_file(in_oprom
);
1154 printerr("Failed to read input file\n");
1158 struct fileobject
*vbt
= NULL
;
1159 if (in_legacy
|| in_oprom
) {
1160 if (!is_valid_vbios(fo
)) {
1161 printerr("Invalid input file\n");
1166 parse_vbios(fo
, &vbt
);
1168 parse_vbt(fo
, &vbt
);
1173 printerr("Failed to find VBT.\n");
1183 } else if (out_vbt
) {
1184 if (write_file(out_vbt
, vbt
)) {
1185 printerr("Failed to write VBT\n");
1188 print("VBT written to %s\n", out_vbt
);
1190 } else if (patch_oprom
) {
1191 fo
= read_file(patch_oprom
);
1193 printerr("Failed to read input file\n");
1196 if (ret
!= 1 && !is_valid_vbios(fo
)) {
1197 printerr("Invalid input file\n");
1200 if (ret
!= 1 && patch_vbios(fo
, vbt
)) {
1201 printerr("Failed to patch VBIOS\n");
1204 if (ret
!= 1 && fix_vbios_header(fo
)) {
1205 printerr("Failed to fix VBIOS header\n");
1208 if (ret
!= 1 && write_file(patch_oprom
, fo
)) {
1209 printerr("Failed to write VBIOS\n");
1214 print("VBIOS %s successfully patched\n", patch_oprom
);