I've been following the steps in here with interest and I'm in the same state you were here.
vbios failed with error -2.
How did you resolve this part?
I've doubled checked the file is in /lib/firmware/radeon/vbios.bin
I even placed another file in /radeon/ but I didn't think that was necessary.
I got my vbios.bin file by running this command:
dd if=/dev/mem of=/boot/vbios.bin bs=65536 skip=12 count=1
on a bare metal linux install
I also tried using a rom file from gpu-z bare metal windows renamed to vbios.bin
Hopefully I won't have to recompile the kernel again, I was kind of surprised how long that took.
I know this post is a bit old but, but I've been the beneficiary of random forum posts in the past and figured it's my turn to give back.
I was able to get this working after a bit of painful trial and error - here are the details of what I did in case it's helpful for anyone.
My setup: ESXi 6.0, AMD Radeon 5450, Ubuntu 18.04, 2 monitors (1 HDMI and 1 DVI). I imagine similar steps will apply to ESXi 6.5, other AMD cards, and other versions of Linux (FWIW I confirmed this worked on Ubuntu 16.04 too)
If you've never compiled a linux kernel before then consider this a good "learning opportunity".
1. Download kernel source and install relevant build utilities
In Ubuntu you can do something like this
Code:
$ apt-get source linux-image-$(uname -r)
$ sudo apt-get build-dep linux-image-$(uname-r)
$ sudo apt-get install libssl-dev
(obviously other distros may have their own analogous steps here - Google is your friend)
My setup extracted the source code into a "linux-4.15.0" folder (this name is used in subsequent steps)
2. You'll need a kernel .config file that informs the build system how to compile the kernel. In Ubuntu I just did
Code:
$ cp /boot/config-$(uname -r) linux-4.15.0/.config
to start with a working Ubuntu config. In the past on other distros I've also done 'make oldconfig' or 'make menuconfig' (from inside the linux kernel source directory), but in this case I found it simplest to just start with the one that Ubuntu uses.
3. Modify the .config file. You can type 'make menuconfig' and hunt down the relevant options, or just open .config in a text editor, and apply these updates:
Code:
# CONFIG_DEBUG_INFO is not set
CONFIG_EXTRA_FIRMWARE="radeon/vbios.bin"
CONFIG_EXTRA_FIRMWARE_DIR="/lib/firmware"
Unsetting DEBUG_INFO is optional - it will make the compile go significantly faster (and consume significantly less disk space). It seems that Ubuntu defaults this to on which was annoying because it filled up my limited disk space on the first attempt.
The 2 EXTRA_FIRMWARE-related lines instruct the kernel build system to compile the video bios binary directly into the kernel. None of the other replies on this topic floating around the internet have ever mentioned doing this, so there may be a way to avoid it. Without these settings, I was stuck with the same "vbios error -2" during boot- for some reason the kernel was unable to access the filesystem during boot (so even though the vbios.bin file was in /lib/firmware/radeon the kernel didn't see it). This issue may be an artifact of Ubuntu's full disk encryption - not an expert on the Linux boot process and don't intend to be

.
4. Apply the "patch" to linux-4.15.0/drivers/gpu/drm/radeon/radeon_bios.c
I would strongly suggest just typing these changes by hand since this file may have changed since the 'diff' floating around the internet, and hence the 'patch' utility may end up making a mess of things. If you don't know C, then consider it yet another learning opportunity. The patch amounts to 3 small changes:
A: add a new #include at the top with the others
Code:
#include <linux/firmware.h>
B: Add a radeon_read_bios_from_firmware function somewhere above the existing radeon_read_bios_from_firmware function. Here is a copy/paste of mine:
Code:
static bool radeon_read_bios_from_firmware(struct radeon_device *rdev)
{
const uint8_t __iomem *bios;
resource_size_t size;
const struct firmware *fw = NULL;
request_firmware(&fw, "radeon/vbios.bin", rdev->dev);
if (!fw) {
DRM_ERROR("No bios file\n");
return false;
}
size = fw->size;
bios = fw->data;
if (!bios) {
DRM_ERROR("Bios missing from bios file\n");
return false;
}
if (size == 0) {
DRM_ERROR("Wrong sig - size is 0!\n");
release_firmware(fw);
return false;
}
if (bios[0] != 0x55 || bios[1] != 0xaa) {
DRM_ERROR("Wrong sig - magic numbers are wrong!\n");
release_firmware(fw);
return false;
}
rdev->bios = kmalloc(size, GFP_KERNEL);
if (rdev->bios == NULL) {
DRM_ERROR("kmalloc failed\n");
release_firmware(fw);
return false;
}
memcpy(rdev->bios, bios, size);
release_firmware(fw);
return true;
}
C. Call the function in B inside the radeon_get_bios function if everything else fails (for me the original last one was "radeon_read_platform_bios", so I added my call after that):
Code:
if (r == false)
r = radeon_read_bios_from_firmware(rdev);
5. Copy your vbios.bin file to /lib/firmware/radeon/vbios.bin.
6. Compile the kernel. There are a few different procedures to do this. The Debian-specific scripts (recommended by Ubuntu and other places on the internet) seemed to be a huge rabbit hole mess when I tried them, but this "old-school" method for Debian-based distros should work:
Code:
make -j8 bindeb-pkg LOCALVERSION=-radeon
The "-j8" will compile in parallel using 8 processors (adjust for your machine).
the LOCALVERSION variable will append this tag onto the final kernel so we can identify it as our patched version.
While it builds you might as well confirm that the settings in step 3 worked - the build system should create a vbios-related object file from the one in /lib/firmware, and put it here: linux-4.15.0/firmware/radeon
Hopefully it just completes successfully but any errors are likely (hopefully?) just a typo from section 4.
7. Install the new kernel, and reboot
If everything went well then you should end up with a bunch of *.deb files 1 folder up from the kernel source folder. On Ubuntu I installed them like this
Code:
sudo dpkg -i linux-*4.15.*radeon*.deb
and rebooted
8. Force X to use the radeon graphics card
On my setup I'm not able to delete the SVGA adapter from ESXi, and Ubuntu/X seems to default to that one as the primary. I forced it to point at my radeon by creating a new file at "/etc/X11/xorg.conf.d/20-radeon.conf" with these contents:
Code:
Section "Device"
Identifier "Radeon 5450"
Driver "radeon"
BusID "PCI:19:0:0"
EndSection
Note: You will need to adjust the BusID for your graphics card. Assuming pass-through is working, you can find the address by doing "lspci | grep VGA". lspci reports the address in base-16, so I think you have to convert to base-10 for the X config. In my case lspci reported "13:00.0" for the passed-through AMD GPU, so I put 19:0:0 in the X config. After creating this file and rebooting everything started working for me, and has been incredibly stable for 1 week+.
Again, I hope these steps are useful for someone.
If anyone more knowledgeable on the video bios loading procedure comes across this, perhaps they can comment on why this song and dance is even necessary in the first place? i.e., is there any technical reason why this functionality cannot be added upstream in the kernel driver and "just work" for users in the future? (sadly, it took about 15 seconds to get GPU pass through working in Windows) This is obviously not a 'user-friendly' solution but I promise it does work!