How do I get my UEFI EDK2 based BIOS to automatically load a driver located in its own firmware volume? - bios

I am using the UEFI EDK2 to create a BIOS. I have modified the FDF to move a driver (both UEFI and legacy versions) from the main firmware volume into a separate firmware volume (FV) that I created strictly to hold the driver.
Before I moved the driver from the main FV, I would see the legacy OROM sign-on during POST. However, since I have moved the driver to the new FV, I no longer see the legacy OROM sign-on. It would seem the legacy OROM is no longer being loaded.
It seems that EDK2 "automatically" loads only certain FVs and then dispatches their drivers, but I can't figure out how these particular FVs are identified in EDK2.
I have searched the EDK2 code for several hours trying to find out where/how the FV HOB is created/initialized, but I cannot find this code. I'm guessing I need to add the new FV's GUID to some list or data structure, but I'm really guessing at this point.
Any pointers would be greatly appreciated.

I found the location in the BIOS where the firmware volume HOBs are created (in a proprietary file). I added code there to create a FV HOB for my new firmware volume.
After that, I had to install a PPI that could process the new firmware volume. Here is the PPI creation code:
static EFI_PEI_FIRMWARE_VOLUME_INFO_PPI mNewFvPpiInfo = {
EFI_FIRMWARE_FILESYSTEM2_GUID,
(VOID*) <Starting address of new FV in the ROM>,
<size of the new FV in the ROM>,
NULL,
NULL
};
static EFI_PEI_PPI_DESCTRIPTOR mNewFvPpi = {
(EFI_PEI_PPI_DESCTRIPTOR_PPI | EFI_PEI_PPI_DESCTRIPTOR_TERMINATE_LIST),
&gEfiPeiFirmwareVolumeInfoPpiGuid,
&mNewFvPpiInfo
};
Here is the code that installs the PPI (placed after the new FV HOB is added to the FV HOB list):
(*ppPeiServices)->InstallPpi(ppPeiServices, &mNewPvPpi);

Related

how to write driver for MX 6 and TJA1100 PHY?

I am working on new costume board based on (i. MX 6Solo6DualLite).and I use (TJA1100 100BASE-T1 PHY) for Automotive Ethernet..
please correct me if my questions don't make sense, or I am in the wrong way.
I want to write driver for this device.. and make sure that it works correctly.
1- I can make sure that the driver works properly in the U-boot step, Right? I mean no need to load Linux kernel, so I have just to add source code C driver in U-boot source code and compile it. I want to do this in U-boot step, so I can limit the numbers of files that initialise all peripheriques, and make it simple as possible since that U-boot can behave like (mini-Os)
2-I don't know how to write this driver (exactly..), so I am looking for the driver (source code) that initialise the Ethernet Controller in any other processor , and initialise another typeof ethernet phy, in order to get an idea and write a similar driver source code for I.MX6 and TJA1100,?
after this i think that i could maybe add some very basic file c For simple Protocol like ARP, for test purpose..
3- is this good idea writing driver code by inspiring from another driver code source?
4 - maybe, if you already have a driver for (i. MX 6Solo6DualLite and TJA1100 100BASE-T1 PHY) can you provide to me please... ?
for my second question i tried to extract from U-boot source code the C file that initialise Ethernet Controller in AM335x, and initialise LAN8710A phy,(in beaglebone black) in order to get an idea and write a similar driver source code but i couldn't found it .. i found network C file for protocol .... but that's disturp me i couldn't seperate them from the real C file that initialise ethernet controller and ethernent Phy .
http://www.denx.de/wiki/U-Boot/SourceCode
There is a driver published on the NXP forum:
https://community.nxp.com/thread/460767
It includes both some bare metal code that should be usable with U-Boot and a Linux driver.

IoT Edge Device Keeping Removed Modules - Sending in Module Twin Lists *BUG*

I have created an IoT Hub Edge device. In the beginning, the default $edgeAgent and $edgeHub modules went in. That's fine. Then I added a "barkModule" (note the lower-case B at the start) -- just a test module to play with D2C event messages and DirectMethod calls to the module.
Later on, I removed that module and added a new one, this time with BarkModule (capital B). Been rocking this way for about a week.
I did this bit of code to get a list of a devices module twins (_deviceTwins is the twins of all the devices on the hub, this is basically just getting all the modules for the device) :
foreach (var _device in _deviceTwins) {
var moduleList = await registryManager.GetModulesOnDeviceAsync(_device.DeviceId);
DeviceList.Add(new DeviceAndModules { DeviceTwin = _device, Modules = moduleList.ToList() });
};
In its module twin list -- I'm getting an entry for both BarkModule and barkModule. Even though my device just has $edgeAgent, $edgeHub and BarkModule modules.
I even went digging in $edgeAgent's module twin, and there's a ton of meta-data event history stuff (seriously, this is absurdly large) -- but there's NO reference to the lowercase-b "barkModule" anywhere.
How is it maintaining this information? Why is this showing up still? Is there a way I can remove this?
This shows the modules:
This shows there's only three:

Is there a way to determine the Physical Sector Size for removable drives with file systems other than NTFS (like FAT16, exFAT...)?

I need a function to get the Physical Sector Size for all kind of system drives, in Win7 or higher.
This is the code that I've used until today, when I found out that it's not working with my external USB HDD (exFAT file system) and with my USB MP3 Player (FAT16). In these cases the function DeviceIoControl fails and I get the exception: "System Error. Code 50. The request is not suported". But it works very well with NTFS volumes.
function GetSectorSize(Drive:Char):DWORD;
var h:THandle;
junk:DWORD;
Query:STORAGE_PROPERTY_QUERY;
Alignment:STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR;
begin
result:=0;
h:=CreateFileW(PWideChar('\\.\'+UpperCase(Drive)+':'),0,FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0);
if h=INVALID_HANDLE_VALUE then RaiseLastOSError;
try
FillChar(Query,SizeOf(Query),0);
Query.PropertyId:=StorageAccessAlignmentProperty;
Query.QueryType:=PropertyStandardQuery;
if not DeviceIoControl(h,IOCTL_STORAGE_QUERY_PROPERTY,#Query,SizeOf(Query),#Alignment,SizeOf(Alignment),junk,nil) then RaiseLastOSError;
result:=Alignment.BytesPerPhysicalSector;
finally
CloseHandle(h);
end;
end;
According to MSDN:
File Buffering
Most current Windows APIs, such as IOCTL_DISK_GET_DRIVE_GEOMETRY and GetDiskFreeSpace, will return the logical sector size, but the physical sector size can be retrieved through the IOCTL_STORAGE_QUERY_PROPERTY control code, with the relevant information contained in the BytesPerPhysicalSector member in the STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR structure. For an example, see the sample code at STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR. Microsoft strongly recommends that developers align unbuffered I/O to the physical sector size as reported by the IOCTL_STORAGE_QUERY_PROPERTY control code to help ensure their applications are prepared for this sector size transition.
This same quote also appears in the following MSDN document:
Advanced format (4K) disk compatibility update
Which includes the following additional information:
The below list summarizes the new features delivered as part of Windows 8 and Windows Server 2012 to help improve customer and developer experience with large sector disks. More detailed description for each item follow.
...
•Provides a new API to query for physical sector size (FileFsSectorSizeInformation)
...
Here’s how you can query for the physical sector size:
Preferred method for Windows 8
With Windows 8, Microsoft has introduced a new API that enables developers to easily integrate 4K support within their apps. This new API supports even greater numbers of scenarios than the legacy method for Windows Vista and Windows 7 discussed below. This API enables these calling scenarios:
•Calling from an unprivileged app
•Calling to any valid file handle
•Calling to a file handle on a remote volume over SMB2
•Simplified programming model
The API is in the form of a new info class, FileFsSectorSizeInformation, with associated structure FILE_FS_SECTOR_SIZE_INFORMATION
FILE_FS_SECTOR_SIZE_INFORMATION structure
This information can be queried in either of the following ways:
•Call FltQueryVolumeInformation or ZwQueryVolumeInformationFile, passing FileFsSectorSizeInformation as the value of FileInformationClass and passing a caller-allocated, FILE_FS_SECTOR_SIZE_INFORMATION-structured buffer as the value of FileInformation.
•Create an IRP with major function code IRP_MJ_QUERY_VOLUME_INFORMATION.
•Call FsRtlGetSectorSizeInformation with a pointer to a FILE_FS_SECTOR_SIZE_INFORMATION-structured buffer. The FileSystemEffectivePhysicalBytesPerSectorForAtomicity member will not have a value initialized by the file system when this structure is returned from FsRtlGetSectorSizeInformation. A file system driver will typically call this function and then set its own value for FileSystemEffectivePhysicalBytesPerSectorForAtomicity.
Your principal error is that you try to get physical sector size from a volume handle rather than from that of an underlying physical device (\\.\PhysicalDriveX). Device's physical sector size doesn't depend on FS and shouldn't be confused with a logical sector size defined by FS properties.

Deleting .inf and .pnf Files

I manually install my driver using an .inf file. Until now, I deleted the oem.inf and .pnf files from the inf folder to uninstall. Whenever I install a new driver I delete/uninstall the old inf and pnf files.
In my old uninstalls (by deleting .inf and .pnf files), I didn't modify or delete any registry settings.
In this case do I want to change or remove any settings from the registry (for example: devnode)?
You should use the SetupUninstallOEMInf function to uninstall the .INF (and subsequently .PNF) files. This will take care of the details. pnputil (on Vista and higher) should do the equivalent thing from the command line. However, this function will not delete drivers that are currently installed (e.g. associated with a devnode).
Why are you uninstalling the old driver first? The user might already installed your driver for at least one devnode. Why not use a Microsoft-sanctioned solution such as DpInst? It will do the work required to update the driver.
Passing SUOI_FORCEDELETE to SetupUninstallOEMInf wouldn't be a good idea, cause you'd end up with lingering .INF references in your devnodes (in the registry).
At work I wrote a utility I called DriverUninstaller that deletes the devnodes and then deleted the INFs. I only use this utility for uninstallations. Upgrades are handled by DpInst, as they should be. The flow is roughly:
Enumerate them with SetupAPI (e.g. by device class if your device class is unique)
For each devnode, call SetupDiCallClassInstaller(DIF_REMOVE, ...)
Call SetupDiBuildDriverInfoList to find all .INF files for my device
For each INF, call SetupUninstallOEMInf
If there'll be interest in this utility, I might be able to persuade my employer to open-source it :-)
As the other answer points out the API to remove drivers on Windows is the SetupUninstallOEMInf method but I figured I'd add a few important notes here:
the INF path parameter must be the file name only (must not include the full path!)
this API requires Administrator privileges (this is not much of a surprise)
on 64-bit systems, the method only works when executed in the context of a 64-bit process (ie. WOW64 doesn't work)
The SetupDiGetDriverInfoDetail API can be used to query information about the relevant INF file(s) to remove for a particular device. And the SetupDiEnumDriverInfo/SetupDiBuildDriverInfoList APIs can be used to enumerate all drivers for a particular device.
// given infFilePath - full path to inf as returned by a query using SetupDiGetDriverInfoDetail
TCHAR* infFileName = GetFileNamePart(infFilePath);
if(SetupUninstallOEMInf(pInf, SUOI_FORCEDELETE, NULL))
{
// success
}else
{
DWORD errCode = GetLastError();
if(errCode == 0x02)
{
// means that the driver INF file was not found
// most likely it was already uninstalled
}else if(errCode == 0x05)
{
// must run as administrator
}else
{
// some other error code.. handle appropriately
}
}
I've open-sourced the code for a tool I wrote to perform driver uninstalls for USB and Media/Image devices. Details here: http://mdinescu.com/software-development/30-driver-hunter-programatically-uninstall-drivers-in-windows

Bootstrap Hard disk access

I'm trying to write a bootstrap loader for the fun of it, I've been using guides such as:
http://www.omninerd.com/articles/PC_Bootstrap_Loader_Programming_Tutorial_in_ASM
http://hem.passagen.se/danma/nboot.htm
http://en.skelix.org/skelixos/tutorial01.php
I'm able to successfully copy over sectors from a floppy disk but when I try to access a harddisk I'm returned an error code from all int 13 functions other than reset. reset disk doesn't return an error.
Is there something special I have to do before int 13 works for hard disks?
Not that I'm aware of. Have you seen http://gaztek.sourceforge.net/osdev/boot/index.html ? That has a list of examples, at least one of which claims to be reading a file from "C:\" (presumably a DOS-formatted harddisk)

Resources