0% found this document useful (0 votes)
84 views41 pages

DXE (PI Vol.2)

Transcription of student course on computer architecture. Full architectural description of EFI and PI computer firmware specification.

Uploaded by

Marc Carpentier
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
84 views41 pages

DXE (PI Vol.2)

Transcription of student course on computer architecture. Full architectural description of EFI and PI computer firmware specification.

Uploaded by

Marc Carpentier
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 41

==================================

======= PI Vol. 2 DXE phase ======

Vol. 2 of the PI address DXE CIS ( Core \


Interface Specification ).

PEI (Pre Efi Initialisation ) phase prior to DXE.

The DXE phase finish when an Operating \


System is successfully booted.

The BDS ( Boot Device Selection ) and DXE \


work together.

The DXE foundation is comprised of Boot \


Services code. So nothing of DXE survive \
OS booting ...

Runtime structure and services can \


DXE drivers produce.

Note that DXE require a valid HOB list.\


PEI phase of the PI CIS is just one of \
many possible method to achieve \
the required HOB.

State if system memory is passed from \


PEI to DXE as a list of position-independant \
structures called HOBs . (Hand Off Blocks).

Components of DXE are :


- DXE foundation
- DXE dispatcher
- DXE drivers

UEFI system table with pointer to \


UEFI Boot Services table and \
UEFI Runtime Services table is passed to \
every DXE module when load.

In addition, the UEFI system table contains :\


- Console services interfaces pointers.
- Pointer to UEFI Configuration table.

The UEFI configuration table contains a list \


of GUID/pointer pairs. The UEFI
Configuration \
Table may include tables such as the \
- DXE Services Dependencies
- HOB list
- ACPI table
- SMBIOS
table
- SAL System table.

The UEFI Boot Services Table contains \


services to access the contents of the handle \
database. The handle database is
where \
protocol interfaces produced by drivers \
are registered. Other drivers can use the \
UEFI Boot Services to look up
these services \
produced by other drivers.

All of the services available in the DXE phase \


may be accessed through a pointer to \
the UEFI System Table.

The DXE Foundation is a boot service image \


that is responsible for producing the following:

• UEFI Boot Services


• UEFI Runtime Services
• DXE Services

The DXE Foundation consumes a HOB list \


and the services of the DXE Architectural \
Protocols to produce the full
complement \
of UEFI Boot Services, UEFI Runtime Services \
and DXE services.

The DXE foundation is an implementation \


of UEFI.

The DXE foundation is backward compatible\


with UEFI 2.0.

2 kind DXE :
- DXE component that use UEFI-only feature.
- DXE component that use extension

DXE dispatcher is part of DXE foundation.


it loads and execute DXE in order that from :
- a priori file from FV
- rules that come from inside driver.

After load all DXE, control is let to BDS. \


The BDS operation is defined in UEFI 2.0.
DXE architectural is divided in many fields :
Security Architectural Allows the DXE Foundation to authenticate files stored in
firmware volumes before they are used
CPU Architectural Provides services to manage caches manage interrupts retrieve the
processors
frequency and query any processor based timers
Metronome Architectural Provides the services required to perform very short
calibrated stalls
Timer Architectural Provides the services required to install and enable the
heartbeat timer inter-
rupt required by the timer services in the DXE Foundation
BDS Architectural Provides an entry point that the DXE Foundation calls once after
all of the
DXE drivers have been dispatched from all of the firmware volumes This
entry point is the transition from the DXE phase to the Boot Device Selection
BDS phase and it is responsible for establishing consoles and enabling the
boot devices required to boot an OS
Watchdog Timer Architectural Provides the services required to enable and disable a
watchdog timer in the platform
Runtime Architectural Provides the services required to convert all runtime
services and runtime
drivers from physical mappings to virtual mappings
Variable Architectural Provides the services to retrieve environment variables and
set volatile environment variables
Variable Write Architectural Protocol
Provides the services to set nonvolatile environment variables
Monotonic Counter Architectural Provides the services required by the DXE
Foundation to manage a 64 bit
monotonic counter
Reset Architectural Provides the services required to reset or shutdown the
platform
Real Time Clock Architectural Provides the services to retrieve and set the current
time and date as well as
the time and date of an optional wake up timer
Capsule Architectural Protocol Provides the services to retrieve and set the
current time and date as well as
the time and date of an optional wake up timer

// DXE Services Table


//
#define DXE_SERVICES_SIGNATURE 0x565245535f455844
#define DXE_SERVICES_REVISION PI_SPECIFICATION_VERSION

typedef struct {
EFI_TABLE_HEADER Hdr;
//
// Global Coherency Domain Services
//
EFI_ADD_MEMORY_SPACE AddMemorySpace;
EFI_ALLOCATE_MEMORY_SPACE AllocateMemorySpace;
EFI_FREE_MEMORY_SPACE FreeMemorySpace;
EFI_REMOVE_MEMORY_SPACE RemoveMemorySpace;
EFI_GET_MEMORY_SPACE_DESCRIPTOR GetMemorySpaceDescriptor;
EFI_SET_MEMORY_SPACE_ATTRIBUTES SetMemorySpaceAttributes;
EFI_GET_MEMORY_SPACE_MAP GetMemorySpaceMap;
EFI_ADD_IO_SPACE AddIoSpace;
EFI_ALLOCATE_IO_SPACE AllocateIoSpace;
EFI_FREE_IO_SPACE FreeIoSpace;
EFI_REMOVE_IO_SPACE RemoveIoSpace;
EFI_GET_IO_SPACE_DESCRIPTOR GetIoSpaceDescriptor;
EFI_GET_IO_SPACE_MAP GetIoSpaceMap;
//
// Dispatcher Services
//
EFI_DISPATCH Dispatch;
EFI_SCHEDULE Schedule;

EFI_TRUST Trust;

//
// Service to process a single firmware volume found in
// a capsule
//
EFI_PROCESS_FIRMWARE_VOLUME ProcessFirmwareVolume;
//
// Extensions to Global Coherency Domain Services
//
EFI_SET_MEMORY_SPACE_CAPABILITIES SetMemorySpaceCapabilities;
} DXE_SERVICES;

The following example shows the UEFI image entry point for an UEFI application.
This application makes use of the
UEFI System Table, UEFI Boot Services Table, UEFI Runtime Services Table, and DXE
Services Table.

EFI_GUID gEfiDxeServicesTableGuid = DXE_SERVICES_TABLE_GUID;


EFI_SYSTEM_TABLE *gST;
EFI_BOOT_SERVICES *gBS;
EFI_RUNTIME_SERVICES *gRT;
DXE_SERVICES *gDS;
EfiApplicationEntryPoint(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
UINTN Index;
BOOLEAN Result;
EFI_STATUS Status;
EFI_TIME *Time;
UINTN NumberOfDescriptors;
EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemorySpaceDescriptor;
gST = SystemTable;
gBS = gST->BootServices;
gRT = gST->RuntimeServices;
gDS = NULL;

for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {

Result = EfiCompareGuid (
&gEfiDxeServicesTableGuid,
&(gST->ConfigurationTable[Index].VendorGuid)
);

if (Result) {
gDS = gST->ConfigurationTable[Index].VendorTable;
}
}
if (gDS == NULL) {
return EFI_NOT_FOUND;
}

//
// Use UEFI System Table to print “Hello World” to the active console
// output device.
//
Status = gST->ConOut->OutputString (gST->ConOut, L”Hello
World\n\r”);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Use UEFI Boot Services Table to allocate a buffer to store the
// current time and date.
//
Status = gBS->AllocatePool (
EfiBootServicesData,
sizeof (EFI_TIME),
(VOID **)&Time
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Use the UEFI Runtime Services Table to get the current
// time and date.
//
Status = gRT->GetTime (&Time, NULL)
if (EFI_ERROR (Status)) {
return Status;
}
//
// Use UEFI Boot Services to free the buffer that was used to store
// the current time and date.
//
Status = gBS->FreePool (Time);
if (EFI_ERROR (Status)) {
return Status;

//

// Use the DXE Services Table to get the current GCD Memory Space Map
//
Status = gDS->GetMemorySpaceMap (
&NumberOfDescriptors,
&MemorySpaceMap
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Use UEFI Boot Services to free the buffer that was used to store
// the GCD Memory Space Map.
//
Status = gBS->FreePool (MemorySpaceMap);
if (EFI_ERROR (Status)) {
return Status;
}
return Status;
}

SAL :
Can physical before SetVirtualAddressMap()
Can virtual and physical after.
Available after ExitBootServices().
ces().
Declare MODULE_TYPE as DXE_SAL_DRIVER \
in the .inf file.
Register SAL services for the system.
May register with \
EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.

Vol2.1 Introduction
Vol2.2 Overview
Vol2.3 Boot manager
Vol2.4 System table
Vol2.5 Boot services
Vol2.6 Runtime capabilities
Vol2.7 DXE services
Vol2.8 Device Path Protocol
Vol2.9 Foundation
Vol2.10 Dispatcher
Vol2.11 Drivers
Vol2.12 Architectural protocols
Vol2.13 EFI_MP_SERVICES_PROTOCOL
Multiprocessor services.
Vol2.14 EFI_STATUS_CODE_RUNTIME_PROTOCOL
Vol2.15 Dependency expressions grammar.

+++++ Shared elements +++++


++++ VOl3. HOB and Status codes ++++

Note that PPI means PEI protocol interface .


PPI are used by PEIM.

++++ VOl3. Shared elements ++++


++++ HOB and Status codes ++++

++++++ ++++++
++ VOL4. MM Management Mode ++
++++++ ++++++

4.1 Overview
4.2 MM fundation entry point
4.3 Management mode system table MMST
4.4 MM Protocols
4.5 UEFI Protocols
4.6 PI PEI PPI's
4.7 MM Childs dispatch protocols
4.8 Interaction with PEI DXE and BDS
4.9 Other notes on MM drivers
4.10 MCA/INIT/PMI protocol
4.11 Extended SAL services
4.12 SMM SPI stack
4.13 Management Mode Backward \
Compatibility Types.

++++++ ++++++
+++++ VOL5. Standards +++++
++++++ ++++++

5.1 Introduction
5.2 SMBus host design
5.3 SMBios host controller codes
5.4 SMBus design
5.5 SMBus PPI codes
5.6 SMBIOS Protocol
5.7 IDE
5.8 S3 Resume
5.9 APCI SDT
5.10 PCI Host bridge
5.11 PCI Platform
5.12 Hot plug PCI
5.13 Super IO
5.14 Super IO and ISA
5.15 CPU IO
5.16 Legacy region
5.17 I²C
5.18 SPI
5.19 Appendix : Error Codes

++++++++++++++++++++++++++

IPF : Itanium Processor Family

SMM : System Management Mode.


SMI : System Management Interrupt.
SMRAM : System Management RAM . \
The memory address where reside \
the SMI ( System Management Interrupt ) .

MM : Management Mode, 2 MM modes \


are defined in PI : Standalone and \
Traditional.
MMI : Management Mode Interrupt.
MMRAM : Memory address range for \
traditional or standalone mode PI \
compliant images. Can be static ram if \
perfect availability required.

MM is implemented :
- with SMM for x86 processors.
- with ARM TZ ( Trust Zone ) for ARM's

IPL : Initial Program Load. The period of time\


to reach function level.

EFI_FV_FILETYPE_MM_CORE_STANDALONE :
MM Foundation file that support MM \
Traditional Mode and MM Standalone Mode.\
This image will be loaded into MMRAM.

Time in SMM life cycle :


- SMM Foundation IPL (Initial Program Load)
- SMM Driver Dispatch.
- Entry to SMM via SMI ( System \
Management Interrupt).

Types in EDK2 :
SEC [¹]: Operate at reset vectors. No service \
defined. But can pass service to PEI using \
conpliant HOB's.
PEI_CORE : PEI Core implementation.
PEIM : PEIM conform with PI
DXE_CORE : Core DXE implementation.
DXE_DRIVER : Boot only DXE.
DXE_RUNTIME_DRIVER : Boot + Runtime DXE.
DXE_SAL [²]: Can both Physical and \
Virtual mode.
DXE_SMM_DRIVER : These are loaded in \
SMRAM only available x86_64 (and IA32).
UEFI_DRIVER : see UEFI 2.0 CIS
UEFI_APPLICATION : see UEFI 2.0 CIS

Phases:
SEC Security phase
PEI Pre-EFI initialisation
DXE Driver Execution Environment
SAL system abstraction layer
BDS Boot device Selection
TSL Transcient System Load
RT Runtime phase.

++++++++++++++++++++++++++

PI,18 p2,68
EFI_TIMER_ARCH_PROTOCOL

#define EFI_TIMER_ARCH_PROTOCOL_GUID \
{ 0x26baccb3, 0x6f42, 0x11d4, {0xbc, 0xe7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } }

extern EFI_GUID gEfiTimerArchProtocolGuid;

struct _EFI_TIMER_ARCH_PROTOCOL {
EFI_TIMER_REGISTER_HANDLER RegisterHandler;
EFI_TIMER_SET_TIMER_PERIOD SetTimerPeriod;
EFI_TIMER_GET_TIMER_PERIOD GetTimerPeriod;
EFI_TIMER_GENERATE_SOFT_INTERRUPT GenerateSoftInterrupt;
};
typedef
EFI_STATUS
(EFIAPI *EFI_TIMER_REGISTER_HANDLER)(
IN EFI_TIMER_ARCH_PROTOCOL *This,
IN EFI_TIMER_NOTIFY NotifyFunction
);
typedef
VOID
(EFIAPI *EFI_TIMER_NOTIFY)(
IN UINT64 Time
);
typedef
EFI_STATUS
(EFIAPI *EFI_TIMER_SET_TIMER_PERIOD)(
IN EFI_TIMER_ARCH_PROTOCOL *This,
IN UINT64 TimerPeriod
);
typedef
EFI_STATUS
(EFIAPI *EFI_TIMER_GET_TIMER_PERIOD)(
IN EFI_TIMER_ARCH_PROTOCOL *This,
OUT UINT64 *TimerPeriod
);
typedef EFI_STATUS
(EFIAPI *EFI_TIMER_GENERATE_SOFT_INTERRUPT)(
IN EFI_TIMER_ARCH_PROTOCOL *This
);

typedef struct _EFI_TIMER_ARCH_PROTOCOL EFI_TIMER_ARCH_PROTOCOL;

++++++++++++++++++++++++++
+++ PI 2.10 The DXE dispatcher +++
++++++++++++++++++++++++++

Explore known firmware volumes sequentially.


- Firstly, FV is validated with SECURITY \
architectural protocol.
- Then FV is searched for an 'a priori', 0 or 1.
If found, drivers listed will be treated in the \
order specified.
- Remaining FV are required to provide a \
dependency expression.

Treatmemt of next_driver()
DXE dispatcher call LoadImage() with \
FilePath on FV.

Note that The DXE core foundation call \


the dispatcher after all required initialisation \
done.

Note that the .DXE dispatcher call the BDS \


after all DXE loaded.

The BDS can still have unable to mount \


console services and open yboot devices \
then it calls DXE dispatcher for \
examining new discovery of FV or change \
in dependencies. then DXE dispatcher \
call BDS anew.

File names in FV are GUID. A priori file is \


a list of fixed length GUID records binary \
packed.

GUID of a priori file ( its name ) :


EFI_FV_FILETYPE_FREEFORM
It must have 1 section of type \
EFI_SECTION_RAW.

When FF in FV have type \


EFI_FV_FIRMWARE_VOLUME_IMAGE ,
1) It is searched in \
EFI_FIRMWARE_VOLUME_HOB2 , \
if found it is passed.
2) A section of type \
EFI_SECTION_DXE_DEPEX if found \
contains dependency expression \
to evaluate against installed entries in \
the protocol database. If evaluate to \
false the driver is passed.
3) A section \
EFI_SECTION_FIRMWARE_VOLUME_IMAGE \
is searched and if found, image is loaded \
into memory. A new handle is created,
EFI_FIRMWMARE_VOLUME2_PROTOCOL \
and EFI_DEVICE_PATH_PROTOCOL are \
installed on the handle.

Dependency expression is a packed \


byte stream of opcodes and operands. \
Several opcode operands are GUID : \
Filename in FV, Protocols.
Postfix notation is used. operations results \
are pushed onto a stack and operands taken \
from stack.
BEFORE <filename> : if present, must be \
1 byte program. When <filename> get TRUE, \
that one must queue in front of the latter.
AFTER <filename> : Found only in a 1 byte \
expression. When <filename> get elected, that \
one must queue follow.
PUSH <protocol GUID> : push boolean onto \
the stack. TRUE if protocol is present.
AND / OR / NOT / TRUE / FALSE.
END : end of program. must . Operate as \
return pop().
SOR : the DXE remains on \
'schedule on request' ( SOR ) list. SOR is \
placed first and must be followed by a \
dependency expression or END. If only END \
it is FALSE.

All entries are required a well formed \


dependency expression. If no dependency, \
must be TRUE+END .

BNF :
stmt :=
expr END |
BEFORE expr END |
nAFTER expr END |
SOR expr END ;

expr :=
TRUE | FALSE |
PUSH guid |
expr |
expr NOT |
expr expr OR |
expr expr AND ;

State machine :
- Driver is UNDISCOVERED.
- Driver DISCOVERED once by dispatcher.
- SOR flag make it UNREQUESTED where \
schedule() can DEPENDENT, else not need.
- DEPENDENT come SCHEDULED when TRUE.
- UNTRUSTED TRUSTED and NEVER_TRUSTED are \
possible state from / to SCHEDULED.
- INITIALIZING when run().
- INITIALIZED when returned from run().
UNDISC -> DISC -----> UNREQUESTED
| |
|---> DEP <----|
|
---------
|
SCHEDULED -->UNTRUSTED-->NEVER_T
| |
TRUSTED <------
|
INITIALIZING ----> INITIALIZED

++++++++++++++++++++++++++

TCG : Trusted Computing Group


TPM : Trusted Platform Module

=============================
+++++++++++
+DOCUMENT Ext4Pkg edk2 module+

Ext4Pkg.efi Driver
Driver handle.
ComponentName2
ComponentName
DriverBinding
ImageDevicePath
LoadedImage

+++++++++++
DOCUMENT
+ Boot Services Install Protocol Interface +

typedef enum {
EFI_NATIVE_INTERFACE
} EFI INTERFACE_TYPE;

EFI_STATUS
gBS->InstallProtocolInterface (
IN OUT EFI_HANDLE *Handle,
IN EFI_GUID *Protocol,
IN EFI_INTERFACE_TYPE InterfaceType,
IN VOID *Interface
);

NOTE: 'Install' an interface onto handle.\


if *Handle is NULL a new is created.

EFI_STATUS
gBS->UninstallProtocolInterface (
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
IN VOID *Interface);
NOTE: If Handle have no more interface, it\
is freed by BS.

EFI_STATUS
gBS->ReinstallProtocolInterface (
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
IN VOID *OldInterface,
IN VOID *NewInterface);

EFI_STATUS

gBS->InstallMultipleProtocolInterfaces (

IN OUT EFI_HANDLE*Handle
....); //EFI_GUID*, VOID* - N

EFI_STATUS

gBS->UninstallMultipleProtocolInterfaces (

IN EFI_HANDLE*Handle,
...); //EFI_GUID*, VOID* - N

+++++++++++
+ Boot Services Open Protocol +

EFI_STATUS gBS->HandleProtocol(
EFI_HANDLE Handle,
EFI_GUID*Protocol,
OUT VOID**Interface
)
EFI_STATUS gBS->OpenProtocol(
EFI_HANDLE Handle,
EFI_GUID*Protocol,
OUT VOID**Interface OPTIONAL,
IN EFI_HANDLE AgentHandle,
IN EFI_HANDLE ControllerHandle,
IN UINT32 Attributes
);

Relation :
HandleProtocol(
Handle, Protocol, Interface) =
OpenProtocol(
Handle, Protocol, Interface,
EfiCoreImageHandle, /* Agent */
NULL, /* Controller */
EFI_OPEN_PROTOCOL\ /*Attributes*/
_BY_HANDLE_PROTOCOL );

Agent : The EFI Core Fundation image handle

Attributes :
EFI_OPEN_PROTOCOL\
10h _BY_DRIVER
08h _BY_CHILD_CONTROLLER
01h _BY_HANDLE_PROTOCOL
02h _GET_PROTOCOL
04h _TEST_PROTOCOL
20h _EXCLUSIVE

EFI_STATUS gBS->CloseProtocol(
EFI_HANDLE Handle,
EFI_GUID*Protocol,
EFI_HANDLE AgentHandle,
EFI_HANDLE ControllerHandle
);

+++++++++++
DOCUMENT
EFI_DRIVER_BINDING_PROTOCOL

NOTE:
- Driver (with image handle) 'produce' 1 or +
instance of DriverBindingProtocol interface.
Each instance have a specific 'install' handle.

#define EFI_DRIVER\
_BINDING_PROTOCOL_GUID\

{0x18A031AB,0xB443,0x4D1A,\
0xA5,0xC0,0x0C,0x09,0x26,0x1E,
0x9F,0x71}

typedef struct _EFI_DRIVER_BINDING\


_PROTOCOL {
EFI_DRIVER_BINDING_PROTOCOL\
_SUPPORTED Supported;\
EFI_DRIVER_BINDING_PROTOCOL\
_START Start;\
EFI_DRIVER_BINDING_PROTOCOL\
_STOP Stop;\
UINT32 Version; //EFI version of driver
EFI_HANDLE ImageHandle; //Handle of\
//Driver Image
EFI_HANDLE BindingHandle; //Handle
//Interface
//Owner
} EFI_DRIVER_BINDING_PROTOCOL.;
NOTE: ImageHandle=BindingHandle\
for single.

typedef EFI_STATUS (EFIAPI *


EFI_DRIVER_BINDING_PROTOCOL_START) (
IN EFI_DRIVER_BINDING_PROTOCOL*This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL*Rem\
-ainingDevicePath OPTIONAL
);
NOTE: Controller have a relative device path \
and produce I/O protocol interfaces.

typedef EFI_STATUS (EFIAPI*


EFI_DRIVER_BINDING_PROTOCOL_STOP) (
IN EFI_DRIVER_BINDING_PROTOCOL*This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer OPTION\
-AL
);
NOTE: If n_child > 0 : Request all be freed.
if n_child==0 : Request unlink.

typedef EFI_STATUS (EFIAPI *


EFI_DRIVER_BINDING_PROTOCOL\
_SUPPORTED) (
IN EFI_DRIVER_BINDING_PROTOCOL*This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL*Rem\
-ainingDevicePath OPTIONAL
);

+++++++++++
+++++++++++

Features/Ext4Pkg/Ext4Pkg/*.c *.h
gExt4ComponentName; \
( EFI_COMPONENT_NAME2_PROTOCOL )
gExt4ComponentName2; \
( EFI_COMPONENT_NAME_PROTOCOL )
gExt4BindingProtocol; \
( EFI_DRIVER_BINDING_PROTOCOL )

Ext4Pkg/Ext4Dxe.h :
#define EXT4_DRIVER_VERSION 0x0000

Ext4Pkg/Ext4Dxe.c :
EFIDRIVER_BINDING_PROTOCOL \
gExt4BindingProtocol = \
{
.Supported = Ext4IsBindingSupported
.Bind = Ext4Bind;
.Stop = Ext4Stop;
.Version = EXT4_DRIVER_VERSION;
.ImageHandle = NULL;
.DriverBindihgHandle = NULL;
}
+++++++++++
EXT4_PARTITION
EXT4_FILE
EXT4_BLOCK_NR
EXT4_INO_NR
EXT4_BLOCK_GROUP_DESC
EXT4_EXTENT
EXT4_DIR_ENTRY
EXT4_DENTRY
EXT4_INODE

Inode.c :
#define EXT4_EXTRA_TIMESTAMP_MASK
#define EXT4_FILE_GET_TIME_GENERIC

File.c :
#define EXT4_INO_PERM_READ_OWNER
#define EXT4_INO_PERM_WRITE_OWNER
#define EXT4_INO_PERM_EXEC_OWNER

BlockMap.c :
#define EXT4_MAX_BLOCK_PATH 4
Ext4Disk.h :
#define EXT4_FT_\
UNKNOWN=0/REG_FILE=1/\
DIR=2/CHRDEV=3/BLKDEV=4/\
FIFO=5/SOCK=6/SYMLINK=7

struct EXT4_EXTENT {
struct EXT4_EXTENT_HEADER {
struct EXT4_EXTENT_INDEX {
struct EXT4_EXTENT_TAIL {
struct EXT4_DIR_ENTRY {
struct EXT4_INODE {
struct EXT4_SUPER_BLOCK {
struct EXT4_BLOCK_GROUP_DESC {
struct EXT4_OSD2 {
struct EXT4_OSD2_HURD {
struct EXT4_OSD2_LINUX {

Ext4Dxe.h :

struct EXT4_FILE {
struct EXT4_DENTRY {

typedef struct _Ext4File EXT4_FILE;


typedef struct _Ext4_Dentry EXT4_DENTRY;

struct EXT4_PARTITION {
EFI_SIMPLE_FILESYSTEM_PROTOCOL;
EFI_DISK_IO_PROTOCOL;
EFI_DISK_IO2_PROTOCOL;
EFI_BLOCK_IO_PROTOCOL;

EXT4_SUPERBLOCK SuperBlock;

LIST_ENTRY Openfiles;
EXT4_FILE*Root;
EXT4_DENTRY*RootDentry;

EXT4_BLOCK_GROUP_DESC*BlockGroups;
EXT4_BLOCK_NUMBER NumberBlocks;

....
};

+++++++++++

In Ext4Bind(..)

OpenProtocol ( DISK_IO )

if fail DISK_IO {
DEBUG( ( DEBUG_ERROR , .. ))
goto error;
}
DEBUG (
( DEBUG_INFO , "[ext4] Controller\
supports DISK_IO\n"
)
);
OpenProtocol ( DISK_IO2 )
if fail DiskIo2 { /* no problem */ }
else { DEBUG(( DEBUG_INFO , \
" Controller have DISKIO2 Protocol\n" ))
}

OpenProtocol ( BLOCK_IO )
If fail BLOCK_IO {
DEBUG( ( DEBUG_ERROR , .. ))
goto error;
}

error :
gBS->CloseProtocol(
Handle,
&gEfiDiskIoProtocolGuid,
BindingProtocol.ImageHandle;
ControllerHandle);
gBS->CloseProtocol(..
&gEfiDiskIo2ProtocolGuid,
..);
gBS->CloseProtocol(..
&gEfiBlockIoProtocolGuid,
..);

+++++++++++
+DOCUMENT CORE EFI INTERFACE+

Ext4Bind( /*have 2 incomes*/ :


EFI_DRIVER_BINDING_PROTOCOL*THIS,\
/* not an income */
EFI_HANDLE ControllerHandle,/*Income 1*/
EFI_DEVICE_PATH * RemainPath/*Income 2*/
);

THEN OpenProtocol ( ) 3 times :


All same 5 head parameters :
ControllerHandle, &Guid, &pProtocol, \
Binding->ImageHandle, ControllerHandle
Not same 6th parameter :
- DISK_IO DiskIo \
EFI_OPEN_PROTOCOL_BY_DRIVER
- DISK_IO2 DiskIo2 \
EFI_OPEN_PROTOCOL_BY_DRIVER
- BLOCK_IO BlockIo \
EFI_OPEN_PROTOCOL_GET_PROTOCOL

Then call Ext4OpenPartition ( ) in Partition.c

Ext4OpenPartition( ) :
- AllocateZeroPool for \
EXT4_PARTITION*Part;
- Set DiskIo/DiskIo2/BlockIo
to members ptr of Part;
- Call Ext4OpenSuperBlock(..) in \
Superblock.c which call :
Ext4ReadDiskIo(..)
Ext4OpenVolume(..)
- Set Part->Interface.Revision=EFI_SIMPLE_\
FILE_SYSTEM_PROTOCOL_REVISION
- Set Part->Interface.OpenVolume=\
Ext4OpenVolume(..) of Directory.c

Ext4OpenVolume( \
EFI_SIMPLE_FILESYSTEM_PROTOCOL*,
EFI_FILE_PROTOCOL**root
);

EXT4_PARTITION { /* Specialize */
EFI_SIMPLE_FILESYSTEM_PROTOCOL\
Interface;
EFI_DISK_IO_PROTOCOL DiskIo;
EFI_DISK_IO2_PROTOCOL DiskIo2;
EFI_BLOCK_IO_PROTOCOL BlockIo;
....
};

EXT4_FILE { /* Specialize */
EFI_FILE_PROTOCOL Protocol;
....
}

Ext4Disk.h : Not linked to PROTOCOL stuff.


Mainly ext4 filesystem.

Ext4Dxe.h : Implements of protocol.


Specializes of protocol table.

Static tables :
gExt4BindingProtocol
gExt4ComponentName
gExt4ComponentName2

Allocated tables :
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* \
(EXT4_PARTITION)
EFI_FILE_PROTOCOL* (EXT4_FILE)

Guids :
gEfiDiskIoProtocolGuid
gEfiDiskIo2ProtocolGuid
gEfiBlockIoProtocolGuid
gEfiSimpleFileSystemProtocolGuid

+++++++++++
+DOCUMENT CORE EFI INTERFACE+

#define EFI_DISK_IO_PROTOCOL_\
REVISION 0x00010000
#define EFI_DISK_IO_PROTOCOL_GUID \

{0xCE345171,0xBA0B,0x11d2,0x8e,0x4F,\
0x00,0xa0,0xc9,0x69,0x72,
0x3b}

struct _EFI_DISK_IO_PROTOCOL {
UINT64 Revision;
EFI_DISK_READ ReadDisk;
EFI_DISK_WRITE WriteDisk;
} EFI_DISK_IO_PROTOCOL;

typedef EFI_STATUS
(EFIAPI *EFI_DISK_READ) (
IN EFI_DISK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN UINT64 Offset,
IN UINTN BufferSize,
OUT VOID );

typedef
EFI_STATUS
(EFIAPI *EFI_DISK_WRITE) (
IN EFI_DISK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN UINT64 Offset,
IN UINTN BufferSize,
IN VOID *Buffer
);

+++++++++++
+DOCUMENT CORE EFI INTERFACE+

#define EFI_BLOCK_IO_PROTOCOL_GUID \
{0x964e5b21,0x6459,0x11d2,\
0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b}

#define EFI_BLOCK_IO_PROTOCOL_\
REVISION2 0x00020001

typedef struct _EFI_BLOCK_IO_PROTOCOL {


UINT64 Revision;
EFI_BLOCK_IO_MEDIA *Media;
EFI_BLOCK_RESET Reset;
EFI_BLOCK_READ ReadBlocks;
EFI_BLOCK_WRITE WriteBlocks;
EFI_BLOCK_FLUSH FlushBlocks;
} EFI_BLOCK_IO_PROTOCOL;

typedef struct {
UINT32 MediaId;
BOOLEAN RemovableMedia;
BOOLEAN MediaPresent;
BOOLEAN LogicalPartition;
BOOLEAN ReadOnly;
BOOLEAN WriteCaching;
UINT32 BlockSize;
UINT32 IoAlign;
EFI_LBA LastBlock;
EFI_LBA LowestAlignedLba;
UINT32 LogicalBlocksPerPhysicalBlock;
} EFI_BLOCK_IO_MED;

typedef EFI_STATUS
(EFIAPI *EFI_BLOCK_RESET) (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN BOOLEAN ExtendedVerification);

typedef EFI_STATUS
(EFIAPI *EFI_BLOCK_READ) (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA LBA,
IN UINTN BufferSize,
OUT VOID * Buffer );

typedef EFI_STATUS
(EFIAPI *EFI_BLOCK_WRITE) (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA LBA,
IN UINTN BufferSize,
IN VOID * Buffer);

typedef EFI_STATUS
(EFIAPI *EFI_BLOCK_FLUSH) (
IN EFI_BLOCK_IO_PROTOCOL *This);

+++++++++++
+DOCUMENT CORE EFI INTERFACE+

#define EFI_SIMPLE_FILE_SYSTEM_\
PROTOCOL_GUID \

{0x0964e5b22,0x6459,0x11d2,0x8e,0x39,\
0x00,0xa0,0xc9,0x69,0x72,0x3b}

#define EFI_SIMPLE_FILE SYSTEM_\


PROTOCOL_REVISION 0x00010000

typedef struct _EFI_SIMPLE_FILE_SYSTEM\


_PROTOCOL {\
UINT64 Revision;\
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL\
_OPEN_VOLUME OpenVolume;\
} EFI_SIMPLE_FILE_SYSTEM_PROTOCOL;

typedef EFI_STATUS (EFIAPI *EFI_SIMPLE\


_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME)\
( IN EFI_SIMPLE\
_FILE_SYSTEM_PROTOCOL *This,
OUT EFI_FILE_PROTOCOL ** Root
);

+++++++++++
+DOCUMENT CORE EFI INTERFACE+

#define EFI_LOADED_\
IMAGE_PROTOCOL_GUID \
{0x5B1B31A1,0x9562,0x11d2,\
{0x8E,0x3F,0x00,0xA0,0xC9,0x69,0x72,0x3B}}

#define EFI_LOADED_\
IMAGE_PROTOCOL_REVISION 0x1000

typedef struct {
UINT32 Revision;
.....
.....
EFI_IMAGE_UNLOAD Unload;
.....
} UEFI_LOADED_IMAGE_PROTOCOL;

typedef EFI_STATUS
(EFIAPI *EFI_IMAGE_UNLOAD) (
IN EFI_HANDLE ImageHandle,
);

//Do it again

typedef enum {
EfiReservedMemoryType,
EfiLoaderCode,
EfiLoaderData,
EfiBootServicesCode,
EfiBootServicesData,
EfiRuntimeServicesCode,
EfiRuntimeServicesData,
EfiConventionalMemory,
EfiUnusableMemory,
EfiACPIReclaimMemory,
EfiACPIMemoryNVS,
EfiMemoryMappedIO,
EfiMemoryMappedIOPortSpace,
EfiPalCode,
EfiPersistentMemory,
EfiUnacceptedMemoryType,
EfiMaxMemoryType
} EFI_MEMORY_TYPE;

#define EFI_LOADED_IMAGE\
_PROTOCOL_GUID \
{0x5B1B31A1,0x9562,0x11d2,\
{0x8E,0x3F,0x00,0xA0,0xC9,0x69,0x72,0x3B}}

#define EFI_LOADED_IMAGE_PROTOCOL\
_REVISION 0x1000

typedef struct {
UINT32 Revision;
EFI_HANDLE ParentHandle;
EFI_System_Table*SystemTable;
// Source location of the image
EFI_HANDLE DeviceHandle;
EFI_DEVICE_PATH_PROTOCOL*FilePath;
VOID *Reserved;
// Image’s load options
UINT32 LoadOptionsSize;
VOID *LoadOptions;
// Location where image was loaded
VOID *ImageBase;
UINT64 ImageSize;
EFI_MEMORY_TYPE ImageCodeType;
EFI_MEMORY_TYPE ImageDataType;
EFI_IMAGE_UNLOAD Unload;
} EFI_LOADED_IMAGE_PROTOCOL;

typedef EFI_STATUS
(EFIAPI *EFI_IMAGE_UNLOAD) (
IN EFI_HANDLE ImageHandle,
);

+++++++++++

ASSERT_EFI_ERROR(status)\
MdePkg/Include/Library/DebugLib.h
EFI_ERROR(status)\
MdePkg/Include/Uefi/UefiBaseType.h
RETURN_ERROR(status)\
MdePkg/include/Base.h

typedef UINTN RETURN_STATUS;


#define RETURN_ERROR(StatusCode) (((INTN)(RETURN_STATUS)(StatusCode)) < 0)
#define ENCODE_WARNING(StatusCode) ((RETURN_STATUS)(StatusCode))
#define ENCODE_ERROR(StatusCode) ((RETURN_STATUS)(MAX_BIT | (StatusCode)))
#define EFIERR(_a) ENCODE_ERROR(_a)
#define EFI_ERROR(A) RETURN_ERROR(A)

///
+++++++++++

+ DOCUMENT Ext4Dxe +

Stop() x1
OpenProtocol ( Controller,
...
bind.DriverBindingHandle
Controller
)
Supported() x2
OpenProtocol ( Controller,
...
bind.DriverBindingHandle
Controller
)

Bind() x3
OpenProtocol ( Controller,
...
bind.ImageHandle
Controller
)
Collation x2
OpenProtocol ( ...
...
ImageHandle
NULL
)

HandleOwner
Guid
.....
Who Open - Agent - Driver or Binding
Who Use - Require - Controller or Null

InstallMultipleProtocolInterface :
On the Controller, AllocPool

+++++++++++

PCH Serial ATA controller


CHN-NGFFSA2242-128
FAT
NTFS
EXT4
PciRoot(0x0)/Pci(0x1f,0x2)/\
Sata(0x0,0x0)/\
HD(4,GPT,074...665,0xce7.c000,0x200.0000)

PCIe and PCI : PCIe more flexible.


Supports all features usual for PCI.
SATA vs PCIe : Same. PCIe is faster with
4 lanes.
MMIO : Feature of PCI. Similar to DMA.

AHCI : Serial ATA advanced host controller


interface.

1217 8621 : O2Micro


Realtek PCIE CardReader
BayHub OZ621/OZ777 Memory Card Reader
O2Micro SD/MMC
Specification 48pin Oz777 PCIe to MMC.
O2Micro Mfg Taiwan.

vim /etc/modprobe.d/sdhci.conf
options sdhci debug_quirks2=4
update-initramfs -u
reboot or.
rmmod sdhci-pci sdhci
modprobe sdhci
modprobe sdhci-pci

+++++++++++
edk2 'build' tool .
- y build.log or --report-file=build.log

The last [LibraryClasses] can change library \


class definition on a per module basis.
FACT :
-[LibraryClasses] in inf file is replaced by \
options in .dsc. Option in dsc is nescessary \
as default for bunch of apps. Options in inf \
file should replace those in dsc.

WORK:
1/ In .dsc specialised [LibraryClasses] section
[LibraryClasses.Common.UEFI_APPLICATION]
PcdLib|MdeModulesPkg/Library/
DxePcdLib/DxePcdLib.inf

2/ In .dsc [Component] Special syntax


3.7.2.3 of writers guide.
PackagePkg/NameDxe/NameDxe.inf {
<LibraryClasses>
PcdLib|MdePkg/Library/DxePcdLib/\
DxePcdLib.inf
}
+++++++++++
Drivers :
PEIM : /MdeModulePkg/Universal/PCD/Pei/Pcd.inf
DXE_DRIVER : /MdeModulePkg/Universal/PCD/Dxe/Pcd.inf

UEFI_APPLICATION :
MdeModulePkg :
CapsuleApp
UiApp
BootManagerMenuApp
DumpDynPcds
HelloWorld
driver + app
ShellPkg/DpDynamicCommand+DpApp
UEFI_APPLICATION + DXE_DRIVER
+++++++++++

5 Methods for access Pcd's


-Feature flag
-Fixed at build
-Patchable in module
-Dynamic
-DynamicEx
All are concept created in EDK outside \
of UEFI specification except Dymamic \
(PI vplume II).

read/write pcd in C program :


in inf :
- lib dependency for PcdLib
- package dependency for MdePkg
in source :
- include <Library/PcdLib.h>
- use PcdLib interface to access value

FixedPcd can be array sizes or indexes. \


Value not change. Can declare in\
[Pcd] or [FixedPcd] of the inf \
FixedPcdGet/Set and PcdGet/Set API \
can be used.
PatchablePcd are value in the binary image \
that can be patched. Can declare in [Pcd] or\
[PatchedPcd] of the inf. PatchPcdGet/Set \
and PcdGet/Set API can be used.

FeatureType pcd must be of type boolean,\


must be declared in the inf file [FeaturePcd]\
section and only accessed with \
FeaturePcdGet API.

Pcd Dynamic can :


- Get value at run time
When,
-from a PCD database : PcdDynamicDefault
-from UEFI variable : PcdDynamicsHII
This type must be declared in .dsc file and be\
unique for whole platform. With an initial value\
which cannot be overwritten by any driver.

+++++++++++
PCD not dynamic are fixed at compile time.
(FeatureFlag / FixedBuild / Patchable).

Dynamic Pcd are two type in build system:

Dynamic : build tool transform\


(token) to ("Parameters" guid, token)

DynamicEx(My guid,token) \
Use specify Guid.

In runtime system, 3 types :


- Platform database. DSC section : \
[PcddDynamicDefault]
[PcdsDynamicExDefault]
- UEFI variable. DSC section : \
[PcdsDynamicHii]
[PcdsDynamicExHii]
- OEM database. DSC section : \
[PcdsDynamicVpd]
[PcdsDynamicExVpd]

+++++++++++
PCD library class

-UiApp via UiApp.inf sub-block in \


[Component] section of MdeModulePkg.dsc
-All shell package via [LibraryClasses] in \
ShellPkg.dsc.

+++++++++++

https://github.com/tianocore/udk

Check with included Shell binaries if load


driver more viable.
If yes, will try a built one too.
+++++++++++

https://github.com/tianocore/edk2/\
tree/edk2-stable202305

+++++++++++

build -a X64 \
-p EdkShell/EdkShell.dsc \
-m Shell/Shell.inf -b RELEASE

+++++++++++

gEfiShellParametersProtocolGuid (GetArgs)
{752f3136-4e16-4fdc-a22a-e5f46812f4ca}
gEfiShellProtocolGuid
{6302d008-7f9b-4f30-87ac-60c9fef5da4e}

3ca : Shell ShellParameters SimpleTextOut ImageDevicePath


LoadImage(Efi/Shellx64.efi)

+++++++++++
Slim Bootloader.

Intel® Time Coordinated Computing


(Intel® TCC).
Prioritizes tasks. Use of silicon (SRAM)
use of Software solution.

Linux Boot :
Firmware is essentially brought to OS.
Then PEI . from early phase to BL.
- remove double tasks

github.com/linuxboot/linuxboot

Result : From reset vector to OS : 0.9s

- case 1 : Linux stored in SPI flash.


- case 2 : in eMMC

eMMC is precursor of current SD. \


Usually soldered directly inside PCB.
Use NAND flash like SSD. Capacity is \
far lower than in the SSD (64GB vs 1000GB).

SD are NAND too.

BIOS are NOR and are readable just like RAM.\


But NOR last 10,000 write, where NAND is\
100,000.

SSD achieve high rate by using several NAND \


chip in parallel, thus reaching required rate\
without limitation.

+++++++++++

Slim Bootloader.
Coreboot ( https://www.coreboot.org/ )

Intel Firmware Support Package.


FSP. Service provider.
FSPwrapper. User in the process of start.

+++++++++++
SBL (slimbootloader)
https://u-boot.readthedocs.io/en/latest/board/intel/slimbootloader.html

https://slimbootloader.github.io/\
getting-started/build-host-setup.html

GCC 7.3 or above


Python 3.6 or above
NASM 2.12.02 or above
IASL 20190509
OpenSSL
Git

On Ubuntu, simply run :


sudo apt-get install build-essential iasl python uuid-dev nasm openssl gcc-
multilib qemu git
note : python-is-python3
note : gcc-multilib obsolete the packages :

binutils-aarch64-linux-gnu
binutils-arm-linux-gnueabi
cpp-12-aarch64-linux-gnu
cpp-12-arm-linux-gnueabi
cpp-aarch64-linux-gnu
cpp-arm-linux-gnueabi
gcc-12-aarch64-linux-gnu-base
gcc-12-aarch64-linux-gnu
gcc-aarch64-linux-gnu
gcc-12-arm-linux-gnueabi-base
gcc-12-arm-linux-gnueabi
gcc-arm-linux-gnueabi
gcc-12-cross-base
gcc-13-cross-base
libasan8-arm64-cross
libasan8-armel-cross
libatomic1-arm64-cross
libatomic1-armel-cross
libc6-arm64-cross
libc6-armel-cross
libc6-dev-arm64-cross
libc6-dev-armel-cross
libgcc-12-dev-arm64-cross
libgcc-12-dev-armel-cross
libgcc-s1-arm64-cross
libgcc-s1-armel-cross
libgomp1-arm64-cross
libgomp1-armel-cross
libhwasan0-arm64-cross
libitm1-arm64-cross
liblsan0-arm64-cross
libstdc++6-arm64-cross
libstdc++6-armel-cross
libtsan2-arm64-cross
libubsan1-arm64-cross
libubsan1-armel-cross
linux-libc-dev-arm64-cross
linux-libc-dev-armel-cross

note : qemu could not find installation \


candidate for qemu. Visit qemu.org . \
Install for binary is qemu-system.
note : to share data between host and \
guest os in qemu, use package samba.
note : to emulate a Virtual Distributed \
Ethernet ( Virtual NIC across hosts) use \
package vde2.

Generate SBLKeys (before build ) :


python $(SBL_ROOT)\BootloaderCorePkg\Tools\GenerateKeys.py -k $SBL_KEY_DIR
export SBL_KEY_DIR=<path to SblKeys directory>

Note : SBL_ROOT=/home/marc/\
slimbootloader
SBL_KEY_DIR=${SBL_ROOT}/SblKeys

git clone https://github.com/slimbootloader\


/slimbootloader.git
cd slimbootloader

python BuildLoader.py <subcommand> <target> <options>


<subcommand> : build or clean
<target> : board name (e.g. apl or qemu)
Example: python BuildLoader.py build qemu
Example: python BuildLoader.py clean

Note : python BuildLoader.py build qemu \


include/produce :
- Cloning QEMU FSP from \
EDK2 repo. cloning:httpd://github.com\
/tianocore/edk2.git. Cloning into \
home/marc/Download/QemuSocPkg/\
QemuFsp.

In output folder get \


Stitch_Components.zip among.

Platform stitching / IFWL :


- Stiching the image
- Flash image. Require programmer.

On QEmu :
Not require Stitching.
To build for qrmu Intel Q35 virtual platform :
python BuildLoader.py build qemu
Output is produced in :
Outputs/qemu/SlimBootloader.bin
Run to shell on qemu :
qemu-system-x86_64 -machine q35 -nographic -serial mon:stdio -pflash
Outputs/qemu/SlimBootloader.bin
============= Intel Slim Bootloader STAGE1A =============
...
============= Intel Slim Bootloader STAGE1B =============
...
============= Intel Slim Bootloader STAGE2 =============
...
==================== OS Loader ====================
Press any key within 1 second(s) to enter the command shell
Shell>
To exit qemu on Linux type CTRL-A then X.

Try Yocto :

Download qemu yocto image :


http://downloads.yoctoproject.org/releases/\
yocto/yocto-2.5/machines/genericx86-64/\\
core-image-minimal-genericx86-64.hddimg

Mount core-image-minimal-genericx86\
-64.hddimg locally and rename bzImage\
to vmlinuz.
ie :
sudo mkdir /mnt/yocto
sudo mount -o loop core-image-minimal\
-genericx86-64.hddimg /mnt/yocto
sudo mv /mnt/yocto/bzImage /mnt\
/yocto/vmlinuz
sudo umount /mnt/yocto

Command for booting Yocto using SBL:


qemu-system-x86_64 -machine q35 \
-m 256 -drive id=mydrive,if=none\
,file=core-image-minimal-genericx86\
-64.hddimg,format=raw \
-device ide-hd,drive=mydrive \
-serial mon:stdio -boot order=d -pflash \
Outputs/qemu/SlimBootloader.bin

Simics :

https://slimbootloader.github.io/\
supported-hardware/qsp.html

https://software.intel.com/content\
/www/us/en/develop/blogs/simics-6\
-looking-at-how-software-uses\
-hardware.html

QSP simics use same image as qemu :


python BuildLoader.py build qemu

QSP SBL does not require stitching the SBL\


into an IFWI.
Install simics :

download at https://software.intel.com/\
content/www/us/en/develop/articles/\
simics-simulator.html

1) get : intel-simics-package-manager\
-(version)-linux64.tar.gz
2) plus : simics6-packages-(version)
3) unpack package manager
4) run ispm-gui . If fail try --no-sandbox option.
5) First time open the app, tell it where\
packages. Platform/Install from repo/\
Browse for bundle. Locate the simics-6\
-packages-(version) then select \
"Create Project".

Installation advise :
/opt/simics
$HOME/simics-projects
$HOME/simics-projects/project1

Install with those parameters could then


be done on the command line :
(unpacked-ispm-directory)/ispm packages \
--install-bundle simics-6-packages\
-(version).ispm --install-dir (install\
-location-for-Simics) --create-project \
(location-for-projects)/(first-project-name)

To enable virtualization :
Intel VT-x can when host and target both \
Intel.
In the simics "package manager" go to \
"project manager" view. Select project \
and press >_ button (open terminal).
type bin/vmp-kernel-install.

Intel installation and upgrade guide :


https://www.intel.com/content/\
www/us/en/developer/articles/guide/\
simics-simulator-installation.html

For update, same 2 downloads, run new \


package manager and tell it \
"browse for bundle" but after selecting, \
continue with the finish button in \
"advanced" mode.
For update each project, in \
"Proect manager", Select the project , \
and select "Manage packages".

Boot to Shell on QSP Simics :


Now proceed to load SlimBootloader.bin \
using Simics CLI method (in Simics terminal):

simics> run-command-file \
targets/qsp-x86/firststeps.simics \
bios_image = \
"/home/(SlimBootloader.bin path)"

+++++++++++

IntelFsp2Pkg/Tools/PatchFv.py
_TempRamInitApi
FspSecCoreT:_TempRamInitApi

FD : Firmware device
FV : Firmware volume
FF : Firmware file

PatchFv.py : patch binary file FSP.fd

FSP.fd -> FSPfinal.fd


Fd is already built. Final Fd is \
post-built created.
Patch FSP info header.
Patch FSP table.
....

+++++++++++

Firmware Support Package ( FSP1.1-2015 \


and FSP2.0-2016 ).
cpu <-> FSP <-> \
Platform firmware bootloader | \
Platform firmware.

FSP support firmware during early startup \


and until full load.

Intel FSP define particularly :


EAS : External Architecture Specification

FSP 1.1 define 6 functions only.


1.2.3 and A.B.C
1/ FspTempRamInit
2/ FspInit
A/ FspMemoryInit
B/ FspTempRamExit
C/ FspSiliconInit
3/ FspNotifyPhase
Firstly : FspTempRamInit
Lastly : FspNotifyPhase
In middle either :
1- FspInit OR
2- FspMemoryInit + TempRamExit +\
FspSiliconInit.

FSP 2.0 define a multi-binaries and time \


period approach and only 5 functions.
FSP-T (Temporary) for SRAM core
FspTempRamInit()
FSP-M (Memory ) for DRAM core
FspMemoryInit()
FspTempRamExit()
FSP-S (Silicon) for silicon initialisation.
FspSiliconInit()
FspNotifyPhase()
FSP-O (Other?) optionnally.

FspInit-1.1 is not used in FSP-2.0.\


Function prototype vary. Functionality same\
with ABC-mode used exclusively.

+++++++++++
++Comparison of functions prototypes++

FspTempRamInit2.0(VOID *FsptUpdDataPtr)
FsptUpdDataPtr=FSPT_UPD.
FspTempRamInit1.1(\
FSP_TEMP_RAM_INIT_PARAMS *\
TempRamInitParamPtr);

FspMemoryInit2.0( IN VOID *FspmUpdDataPtr

OUT VOID **HobListPtr);


FspmUpdDataPtr=FSPM_UPD >
HobListPtr=HOB list.
FspMemoryInit1.1(
\
IN OUT FSP_MEMORY_INIT_PARAMS*\
FspMemoryInitParamPtr
);

FspTempRamExit2.0( IN VOID*
TempRamExitParamPtr
);
TempRamExitParamPtr=NULL or defined in \
integration guide.
FspTempRamExit1.1(
IN VOID*
TempRamExitParamPtr
);
/* 1.1 & 2.0 the same for FspTempRamExit */

FspSiliconInit2.0(VOID *FspsUpdDataPtr
);
FspsUpdDataPtr
= FDPS_UPD
FspSiliconInit1.1(
N OUT VOID *\
FspSiliconInitParamPtr
);

FspNotifyPhase2.0(
\
IN NOTIFY_PHASE_PARAMS * \
NotifyPhaseParamPtr
);
FspNotifyPhase2.0(
\
IN NOTIFY_PHASE_PARAMS * \
NotifyPhaseParamPtr
);
/*1.1-2015; and 2.0-2016 \
same FspNotifyPhase*/

#########################
###### EAS 1.1 final (2015) ######
#########################

--- 32 bit only


--- Replaced by Intel FSP 2
--- Use as reference.

UPD / VPD are :


- Updatable Product Data
- Vital Product Data
Configuration data is exchanged between\
consumer and producer of FSP.

BSF :
Boot Setting File.
Ressemble BIOS parameters.

EAS 1.1 Final (2015) :


FSP Single binary.
VPD UPD structure definition
BSF boot setting file
Separately the BCT binary configuration tool.

CAR (enable/disable) : Cache as RAM

&&&&&&&&&&&&&&&&&&&&&&&&

typedef EFI_STATUS
( EFIAPI*FSP_TEMP_RAM_INIT )
( IN FSP_TEMP_RAM_INIT_PARAMS*
TempRamInitParamPtr );
typedef struct {
UINT32 MicrocodeRegionBase,
UINT32 MicrocodeRegionLength,
UINT32 CodeRegionBase,
UINT32 CodeRegionLength
} FSP_TEMP_RAM_INIT_PARAMS;

//All base paragraph aligned


//Code region ask FSP to enable
//code caching in the address range
On return ECX and EDX contains
start and end of a writable memory region.
typically, ESP loaded with EDX end.

The FSP_INFO_HEADER contains offset of \


TempRamInit relatively of base address of \
FSP binary.
&&&&&&&&&&&&&&&&&&&&&&&&

# FspInit API
The trick :
temp ram must be available some time after\
big ram initialized. So the bootloader can\
migrate its data in temporary memory to\
main memory.

Either
- FspInit
Or
- FspMemoryInit
+TempRamExit
+FspSiliconInit

EFI_STATUS
(EFIAPI *FSP_INIT) (
IN OUT FSP_INIT_PARAMS *FspInitParamPtr
);

typedef struct {
VOID *NvsBufferPtr;
//Non volatile data storage if available
VOID *RtBufferPtr;
CONTINUATION_PROC ContinuationFunc;
} FSP_INIT_PARAMS;

typedef VOID (*CONTINUATION_PROC) (


IN EFI_STATUS Status,
IN VOID *HobListPtr
);

typedef struct {
FSP_INIT_RT_COMMON_BUFFER Common;
..... // Optional platform specific data structure
} FSP_INIT_RT_BUFFER;
typedef struct {
UINT32 *StackTop;
UINT32 BootMode;
VOID *UpdDataRgnPtr;
UINT32 BootLoaderTolumSize;
UINT32 Reserved[6];
} FSP_INIT_RT_COMMON_BUFFER;

StackTop : preferred tip from BL


BootMode (indicated by firmware to FSP) :
#define BOOT_WITH_FULL_CONFIGURATION 0x00
#define BOOT_ASSUMING_NO_CONFIGURATION_CHANGES 0x02
#define BOOT_ON_S3_RESUME 0x11
#define BOOT_ON_FLASH_UPDATE 0x12
UpdDataRgnPtr : point to UPD_DATA_REGION \
to pass options.
BootLoaderTolumSize : BL want how much x4K
below "top of low usable memory " TOLUM.

On return EAX is non-zero if fail.

&&&&&&&&&&&&&&&&&&&&&&&&

Client notify FSP of what he does,


so FSP can do related tasks.

# NotifyPhase API(FSP 1.1)


EFI_STATUS
(EFIAPI *FSP_NOTIFY_PHASE) (
IN NOTIFY_PHASE_PARAMS *NotifyPhaseParamPtr
);

typedef struct {
FSP_INIT_PHASE Phase;
} NOTIFY_PHASE_PARAMS;

typedef enum {
EnumInitPhaseAfterPciEnumeration = 0x20
EnumInitPhaseReadyToBoot = 0x40
} FSP_INIT_PHASE;

&&&&&&&&&&&&&&&&&&&&&&&&

typedef
EFI_STATUS
(
EFIAPI *FSP_MEMORY_INIT) (
IN OUT FSP_MEMORY_INIT_PARAMS * \
FspMemoryInitParamPtr
);

typedef struct {
VOID *NvsBufferPtr;
VOID *RtBufferPtr;
VOID **HobListPtr;
} FSP_MEMORY_INIT_PARAMS;

typedef EFI_STATUS
(EFIAPI *FSP_TEMP_RAM_EXIT) (
IN OUT VOID *TempRamExitParamPtr
);

typedef EFI_STATUS
(EFIAPI *FSP_SILICON_INIT) (
IN OUT VOID *FspSiliconInitParamPtr
);

#########################
####### FSP 2.0 (2016) #######
#########################
typedef EFI_STATUS
(EFIAPI *FSP_TEMP_RAM_INIT) (
IN VOID *FsptUpdDataPtr);

typedef struct {
UINT64 Signature;
UINT8 Revision;
UINT8 Reserved[23];
} FSP_UPD_HEADER;
typedef struct {
FSP_UPD_HEADER UpdHeader;
Platform specific parameters;
...
} FSPT_UPD;

----------------------------
---------- FSP 2.0 ----------

typedef
EFI_STATUS

(EFIAPI *FSP_MEMORY_INIT) (

IN VOID *FspmUpdDataPtr

OUT VOID **HobListPtr;

);

----------------------------
---------- FSP 2.0 ----------

typedef struct {
FSP_UPD_HEADER UpdHeader;
....
} FSP_SUPD;

Addresses are 64 bits.


BL name is BSP.
FSP is called in flat 32 bits.
(FSP is in 32 bit world !).

All FSP API's defined in FSP_INFO_HEADER\


are 32 bits.

----------------------------
---------- FSP 2.0 ----------

typedef struct {
FSP_UPD_HEADER UpdHeader;
FSPM_ARCH_UPD FspmArchUpd;
...
} FSPM_UPD;

typedef struct {
UINT8 Revision;
UINT8 Reserved[3]
VOID *NvsBufferPtr;
VOID *StackBase;
UINT32 StackSize;
UINT32 BootLoaderTolumSize;
UINT32 BootMode;
UINT8 Reserved1[8];
} FSPM_ARCH_UPD

#########################
#########################
#########################
vmxmon
in simics-packages/simics6/bin\
/install_vmxmon
and after install simics-packages/simics6\
/vmxmon/scripts/install

Fir users of vmware :


sudo vmware-modconfig \
--console --install-all

#########################

QSP is an emulated standard PC (Probably \


with adapt at run time).
It means Quick Start Platform).

simics-packages/simics-qsp-x86-6.0.67\
/targets/qsp-x86\
/qsp-hdd-boot.simics

#########################
_FFS_

EFI_PEI_FFS_FIND_NEXT_VOLUME2 FfsFindNextVolume;
EFI_PEI_FFS_FIND_NEXT_FILE2 FfsFindNextFile;
EFI_PEI_FFS_FIND_SECTION_DATA2

EFI_FFS_FILE_HEADER
EFI_FFS_FILE_HEADER2
EFI_FFS_VOLUME_TOP_FILE_GUID
EFI_PEI_FFS_FIND_BY_NAME FfsFindFileByName;
EFI_PEI_FFS_GET_FILE_INFO FfsGetFileInfo;
EFI_PEI_FFS_GET_VOLUME_INFO FfsGetVolumeInfo;
EFI_PEI_REGISTER_FOR_SHADOW RegisterForShadow;
EFI_PEI_FFS_FIND_SECTION_DATA3 FindSectionData3;
EFI_PEI_FFS_GET_FILE_INFO

typedef EFI_STATUS
(EFIAPI *EFI_PEI_FFS_FIND_NEXT_VOLUME2) (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN UINTN Instance,
OUT EFI_PEI_FV_HANDLE *VolumeHandle);

typedef EFI_STATUS
(EFIAPI *EFI_PEI_FFS_FIND_NEXT_FILE2) (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN EFI_FV_FILETYPE SearchType,
IN CONST EFI_PEI_FV_HANDLE FvHandle,
IN OUT EFI_PEI_FILE_HANDLE *FileHandle);
EFI_FV_FILETYPE_FFS_MIN
EFI_FV_FILETYPE_FFS_MAX

typedef EFI_STATUS
(EFIAPI *EFI_PEI_FFS_FIND_SECTION_DATA2) (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN EFI_SECTION_TYPE SectionType,
IN EFI_PEI_FILE_HANDLE FileHandle,
OUT VOID **SectionData
);

typedef EFI_STATUS
(EFIAPI *EFI_PEI_FFS_FIND_SECTION_DATA3) (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN EFI_SECTION_TYPE SectionType,
In UINTN SectionInstance
IN EFI_PEI_FILE_HANDLE FileHandle,
OUT VOID **SectionData
OUT UINT32 *AuthenticationStatus

);

EFI_FV_FILETYPE_....
example : EFI_FV_FILETYPE_DXE_CORE
All are segmented except \
EFI_FV_FILETYPE_RAW which is not.\
Then for RAW, file data is any type.\
For all, data start at the begin of the file \
in FV and is followed by file header.

EFI_FIRMWARE_FILE_SYSTEM3_GUID \
indicates support for \
FFS_ATTRIB_LARGE_SIZE and thus support \
for files 16MB or larger.
EFI_FIRMWARE_FILE_SYSTEM2_GUID \
volume does not contain large files. \
Files 16 MB or larger use
a \
EFI_FFS_FILE_HEADER2 and smaller files use \
EFI_FFS_FILE_HEADER.

EFI_FIRMWARE_FILE_SYSTEM2_GUID
allows backward compatibility is compatible \
with older pc software

EFI_FFS_FILE_HEADER2=\
EFI_FFS_FILE_HEADER \
& UINT64 extended size.

// {1BA0062E-C779-4582-8566-336AE8F78F09}
#define EFI_FFS_VOLUME_TOP_FILE_GUID \
{ 0x1BA0062E, 0xC779, 0x4582, 0x85, 0x66, 0x33, 0x6A, \
0xE8, 0xF7, 0x8F, 0x9 }

typedef struct {
UINT8 Size[3];
EFI_SECTION_TYPE Type;
} EFI_COMMON_SECTION_HEADER;
typedef struct {
UINT8 Size[3];//Must be 0xffffff
EFI_SECTION_TYPE Type;
UINT32 ExtendedSize;
} EFI_COMMON_SECTION_HEADER2;

Leaf sections :
#define EFI_SECTION_PE32 0x10
#define EFI_SECTION_PIC 0x11
#define EFI_SECTION_TE 0x12
#define EFI_SECTION_DXE_DEPEX 0x13
#define EFI_SECTION_VERSION 0x14
#define EFI_SECTION_USER_INTERFACE 0x15

#define EFI_SECTION_COMPATIBILITY16 0x16


#define EFI_SECTION_FIRMWARE_VOLUME_IMAGE 0x17
#define EFI_SECTION_FREEFORM_SUBTYPE_GUID 0x18
#define EFI_SECTION_RAW 0x19
#define EFI_SECTION_PEI_DEPEX 0x1B
#define EFI_SECTION_MM_DEPEX 0x1C

Container sections :
#define EFI_SECTION_COMPRESSION 0x01
#define EFI_SECTION_GUID_DEFINED 0x02
#define EFI_SECTION_DISPOSABLE 0x03

typedef struct {

EFI_COMMON_SECTION_HEADER CommonHeader;

EFI_GUID SubTypeGuid;

} EFI_FREEFORM_SUBTYPE_GUID_SECTION;

typedef struct {

EFI_COMMON_SECTION_HEADER2 CommonHeader;
EFI_GUID SubTypeGuid;

} EFI_FREEFORM_SUBTYPE_GUID_SECTION2;

typedef struct {
EFI_COMMON_SECTION_HEADER CommonHeader;
EFI_GUID SectionDefinitionGuid;
UINT16 DataOffset;
UINT16 Attributes;
// GuidSpecificHeaderFields;
} EFI_GUID_DEFINED_SECTION;

typedef struct {
EFI_COMMON_SECTION_HEADER2 CommonHeader;
EFI_GUID SectionDefinitionGuid;
UINT16 DataOffset(¹);
UINT16 Attributes;
// GuidSpecificHeaderFields;
} EFI_GUID_DEFINED_SECTION2;

-- DataOffset
: --
Contains the offset in bytes from \
the beginning of the common header \
to the first byte of the data.
--------------

typedef struct {
UINT8 ZeroVector[16];
Reserved for use by intr or reset.
pointing to volume.
EFI_GUID FileSystemGuid;
EFI_FIRMWARE_FILE_SYSTEM2\
_GUID ( all files are < 16MB ) or\
EFI_FIRMWARE_FILE_SYSTEM3\
_GUID ( file size PI 1.8 spec)
UINT64 FvLength;
Total length include header.
UINT32 Signature;
ascii[4] : "_FVH"
EFI_FVB_ATTRIBUTES_2 Attributes;
UINT16 HeaderLength;
UINT16 Checksum;
UINT16 ExtHeaderOffset;
UINT8 Reserved[1];
UINT8 Revision;
EFI_FV_BLOCK_MAP BlockMap[];
} EFI_FIRMWARE_VOLUME_HEADER;

--- ExtHeaderOffset : ---


Offset, relative to the start of the header, \
of the extended header (EFI_FIRMWARE_\
VOLUME_EXT_HEADER) or
zero if there is \
no extended header. The extended header \
is followed by zero or more variable length \
extension
entries. Each extension entry is \
prefixed with the EFI_FIRMWARE_VOLUME_\
EXT_ENTRY structure (see \
“Related
Definitions” below), which defines \
the type and size of the extension entry. \
The extended header is always 32-bit
\
aligned relative to the start of the \
FIRMWARE VOLUME.
If there is an instance \
of the EFI_FIRMWARE_VOLUME_EXT_\
HEADER , then the firmware shall build an \
instance
of the Firmware Volume Media \
Device Path (ref Vol2, Section 8.2).

---------------------

typedef struct {
UINT32 NumBlocks;
UINT32 Length;
} EFI_FV_BLOCK_MAP;

typedef struct {
EFI_GUID FvName;
UINT32 ExtHeaderSize;
} EFI_FIRMWARE_VOLUME_EXT_HEADER;

#########################
typedef struct _EFI_PEI_FIRMWARE_VOLUME_PPI {
EFI_PEI_FV_PROCESS_FV ProcessVolume;
EFI_PEI_FV_FIND_FILE_TYPE FindFileByType;
EFI_PEI_FV_FIND_FILE_NAME FindFileByName;
EFI_PEI_FV_GET_FILE_INFO GetFileInfo;
EFI_PEI_FV_GET_INFO GetVolumeInfo;
EFI_PEI_FV_FIND_SECTION FindSectionByType;
EFI_PEI_FV_GET_FILE_INFO2 GetFileInfo2;
EFI_PEI_FV_FIND_SECTION2 FindSectionByType2;
UINT32 Signature;
UINT32 Revision;
} EFI_PEI_FIRMWARE_VOLUME_PPI;

typedef struct_EFI_FIRMWARE_VOLUME_PROTOCOL {
EFI_FV_GET_ATTRIBUTES GetVolumeAttributes;
EFI_FV_SET_ATTRIBUTES SetVolumeAttributes;
EFI_FV_READ_FILE ReadFile;
EFI_FV_READ_SECTION ReadSection;
EFI_FV_WRITE_FILE WriteFile;
EFI_FV_GET_NEXT_FILE GetNextFile;
UINT32 KeySize
EFI_HANDLE ParentHandle;
EFI_FV_GET_INFO GetInfo;
EFI_FV_SET_INFO SetInfo;
} EFI_FIRMWARE_VOLUME2_PROTOCOL;

#########################

#########################

+FSP image binary format in FSP 2.0+

-- Inside FD --
FFV (Firmware volume header +\
Firmware volume extension header.
...align 8
FFS
...align 8
FFS
....
...align 8
FFS
(FFS are 8 byte aligned)
--Inside FFS --
Firmware File Header
Section Header
Raw data or Firmware Image.

-- Inside Firmware Image --


FSP_INFO_HEADER
FSP_INFO_EXTENDED_HEADER

You might also like