* Patch an Intel Option ROM with new VBT. * Caller has to make sure that VBIOS and VBT are valid. * Return 1 on error. */
| 1019 | * Return 1 on error. |
| 1020 | */ |
| 1021 | static int patch_vbios(struct fileobject *fo, |
| 1022 | const struct fileobject *fo_vbt) |
| 1023 | { |
| 1024 | optionrom_header_t *oh = (optionrom_header_t *)fo->data; |
| 1025 | struct vbt_header *head; |
| 1026 | |
| 1027 | struct fileobject *old_vbt = NULL; |
| 1028 | parse_vbios(fo, &old_vbt); |
| 1029 | |
| 1030 | if (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)) { |
| 1034 | free_fo(old_vbt); |
| 1035 | return 1; |
| 1036 | } |
| 1037 | fo = remalloc_fo(fo, fo->size - vbt_size(old_vbt)); |
| 1038 | if (!fo) { |
| 1039 | printerr("Failed to allocate memory\n"); |
| 1040 | free_fo(old_vbt); |
| 1041 | return 1; |
| 1042 | } |
| 1043 | oh = (optionrom_header_t *)fo->data; |
| 1044 | oh->vbt_offset = 0; |
| 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, |
| 1048 | vbt_size(old_vbt)); |
| 1049 | oh->vbt_offset = 0; |
| 1050 | } else { |
| 1051 | /* New VBT overwrites existing one - Clear memory */ |
| 1052 | memset(fo->data + oh->vbt_offset, 0xff, |
| 1053 | vbt_size(old_vbt)); |
| 1054 | } |
| 1055 | |
| 1056 | free_fo(old_vbt); |
| 1057 | } |
| 1058 | |
| 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"); |
| 1063 | return 1; |
| 1064 | } |
| 1065 | |
| 1066 | oh->vbt_offset = fo->size; |
| 1067 | fo = remalloc_fo(fo, fo->size + vbt_size(fo_vbt)); |
| 1068 | if (!fo) { |
| 1069 | printerr("Failed to allocate memory\n"); |
| 1070 | return 1; |
| 1071 | } |
| 1072 | oh = (optionrom_header_t *)fo->data; |
| 1073 | } |
| 1074 | |
| 1075 | head = (struct vbt_header *)((u8 *)oh + oh->vbt_offset); |
| 1076 | memcpy(head, fo_vbt->data, vbt_size(fo_vbt)); |
| 1077 | |
| 1078 | return 0; |
no test coverage detected