Skip to content

Instantly share code, notes, and snippets.

@cleanbaja
Created February 10, 2023 23:28
Show Gist options
  • Save cleanbaja/3fcdc6c09197cb6c1ee5eb657f97124f to your computer and use it in GitHub Desktop.
Save cleanbaja/3fcdc6c09197cb6c1ee5eb657f97124f to your computer and use it in GitHub Desktop.
/*
* convert_vfct.c - convert VFCT ACPI table into multiple ATOMBIOS roms
*
* Copyright (C) 2023 by @cleanbaja
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/mman.h>
/*
* NOTE: The expanded roms can be disassembled using the following tool...
* https://github.com/cleanbaja/AtomDis
*/
#pragma pack(1)
struct acpi_header {
char signature[4];
uint32_t length;
uint8_t revision;
uint8_t checksum;
uint8_t oem[6];
uint8_t oem_table[8];
uint32_t oem_revision;
uint32_t creator_id;
uint32_t creator_revision;
};
struct vfct_header {
uint32_t pci_bus;
uint32_t pci_dev;
uint32_t pci_func;
uint16_t pci_vendor_id;
uint16_t pci_device_id;
uint16_t ssvid;
uint16_t ssid;
uint32_t revision;
uint32_t length;
};
struct vbios_content {
struct vfct_header hdr;
uint8_t content[];
};
typedef struct acpi_vfct {
struct acpi_header hdr;
uint8_t uuid[16];
uint32_t vbios_offset;
uint32_t lib1_offset;
uint32_t rsvd[4];
} acpi_vfct_t;
#pragma pack()
void dump_bios_images(acpi_vfct_t* region) {
uint32_t off = region->vbios_offset;
int index = 1;
while ((off + sizeof(struct vfct_header)) < region->hdr.length) {
struct vbios_content* vbios = (struct vbios_content *)((uintptr_t)region + off);
off += vbios->hdr.length + sizeof(struct vfct_header);
printf(
"convert_vfct: found ATOMBIOS for PCI device %02d:%02d.%d (id=%x:%x)\n",
vbios->hdr.pci_bus, vbios->hdr.pci_dev, vbios->hdr.pci_func,
vbios->hdr.pci_vendor_id, vbios->hdr.pci_device_id
);
int rom_fd = 0;
if (index == 1) {
rom_fd = open("vbios.bin", O_WRONLY | O_CREAT, 0644);
} else {
char filename_buf[256] = {0};
snprintf(filename_buf, 256, "vbios%d.bin", index);
rom_fd = open(filename_buf, O_WRONLY | O_CREAT, 0644);
}
index++;
write(rom_fd, vbios->content, vbios->hdr.length);
close(rom_fd);
}
}
int main(int argc, char** argv) {
if (argc < 2)
return 0;
int fd = open(argv[1], O_RDONLY);
struct stat stat;
fstat(fd, &stat);
acpi_vfct_t* region = (acpi_vfct_t *)mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
struct vbios_content* vbios = (struct vbios_content *)((uintptr_t)region + region->vbios_offset);
dump_bios_images(region);
munmap(region, stat.st_size);
close(fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment