This Guide will show you how to create an UEFI Port for your Device.
Booting Windows/Linux on Sony/Google Device will wipe your UFS Clean! (Unable to recover)
Table of Contents |
---|
|
To Port UEFI to your Phone, It needs the following things:
- An Snapdragon SoC
xbl
oruefi
in/dev/block/by-name/
fdt
in/sys/firmware/
It's also recommended to have already some Knowlege about Linux and Windows.
Also a Brain is required to do this.
Lets begin with Copying Files.
Copy the fdt
File from /sys/firmware/
and Place it as <Device Codename.dtb>
under ./Resources/DTBs/
.
Extract your xbl
or uefi
from /dev/block/by-name/
and Place it somewhere you can reach it:
# ADB Shell (Might Require Root)
dd if=/dev/block/by-name/<UEFI Partition> of=/<UEFI Partition>.img
# Linux
adb pull /<UEFI Partition>.img
After Copying the xbl
File or the uefi
File, Extract all UEFI Binaries from it with UEFIReader.
A Compiled Version is Pinned in #gerneral
in our Discord.
Here is how you Use it:
# Windows
UEFIReader.exe <UEFI Partition>.img out
Now Move all the output Files from UEFI Reader in Mu-Qcom/Binaries/<Device Codename>/
.
Then Execute CleanUp.sh
in the Binaries Folder once.
Every Device has its own config file to define some device specific things like: SoC.
Create a File called <Device Codename>.conf
in Mu-Qcom/Resources/Configs/
.
It should contain at least this:
# General Configs
TARGET_DEVICE_VENDOR="<Device Vendor>"
# UEFI FD Configs
TARGET_FD_BASE="<FD Base>"
TARGET_FD_SIZE="<FD Size>"
TARGET_FD_BLOCKS="<FD Blocks>"
<FD Base/Size Value>
is the UEFI FD Value in the MemoryMap (uefiplat.cfg).
<FD Blocks>
is the Number of Blocks UEFI FD has, <UEFI FD Size> / 0x1000
.
Struckture of the Device Files:
./Platforms/<Device Vendor>/<Device Codename>Pkg/
├── Include
│ ├── ACPI.inc
│ ├── APRIORI.inc
│ ├── DXE.inc
│ └── RAW.inc
├── Library
│ ├── DeviceMemoryMapLib
│ │ ├── DeviceMemoryMapLib.c
│ │ └── DeviceMemoryMapLib.inf
│ └── DeviceConfigurationMapLib
│ ├── DeviceConfigurationMapLib.c
│ └── DeviceConfigurationMapLib
├── PlatformBuild.py
├── <Device Codename>.dec
├── <Device Codename>.dsc
└── <Device Codename>.fdf
Lets begin with the .dsc
File
Create a File called <Device Codename>.dsc
in Mu-Qcom/Platforms/<Device Vendor>/<Device Codename>Pkg/
.
Here is an template:
##
#
# Copyright (c) 2011 - 2022, ARM Limited. All rights reserved.
# Copyright (c) 2014, Linaro Limited. All rights reserved.
# Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.
# Copyright (c) 2018, Bingxing Wang. All rights reserved.
# Copyright (c) Microsoft Corporation.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
################################################################################
#
# Defines Section - statements that will be processed to create a Makefile.
#
################################################################################
[Defines]
PLATFORM_NAME = <Device Codename>
PLATFORM_GUID = <GUID>
PLATFORM_VERSION = 0.1
DSC_SPECIFICATION = 0x00010005
OUTPUT_DIRECTORY = Build/<Device Codename>Pkg
SUPPORTED_ARCHITECTURES = AARCH64
BUILD_TARGETS = RELEASE|DEBUG
SKUID_IDENTIFIER = DEFAULT
FLASH_DEFINITION = <Device Codename>Pkg/<Device Codename>.fdf
USE_DISPLAYDXE = 0
# Set this to 1 If your Device is A/B Device
AB_SLOT_SUPPORT = 0
# If your SoC has multimple variants define the Number here
# If not don't add this Define
SOC_TYPE = 2
# If your SoC has multimple variants keep this Build Option
# If not don't add "-DSOC_TYPE=$(SOC_TYPE)" to the Build Options.
[BuildOptions]
*_*_*_CC_FLAGS = -DSOC_TYPE=$(SOC_TYPE)
[LibraryClasses]
DeviceMemoryMapLib|<Device Codename>Pkg/Library/DeviceMemoryMapLib/DeviceMemoryMapLib.inf
DeviceConfigurationMapLib|<Device Codename>Pkg/Library/DeviceConfigurationMapLib/DeviceConfigurationMapLib.inf
[PcdsFixedAtBuild]
# DDR Start Address
gArmTokenSpaceGuid.PcdSystemMemoryBase|<Start Address>
# Device Maintainer
gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor|L"<Your Github Name>"
# CPU Vector Address
gArmTokenSpaceGuid.PcdCpuVectorBaseAddress|<CPU Vector Base Address>
# UEFI Stack Addresses
gEmbeddedTokenSpaceGuid.PcdPrePiStackBase|<UEFI Stack Base Address>
gEmbeddedTokenSpaceGuid.PcdPrePiStackSize|<UEFI Stack Size>
# SmBios
gQcomPkgTokenSpaceGuid.PcdSmbiosSystemVendor|"<Device Vendor>"
gQcomPkgTokenSpaceGuid.PcdSmbiosSystemModel|"<Device Model>"
gQcomPkgTokenSpaceGuid.PcdSmbiosSystemRetailModel|"<Device Codename>"
gQcomPkgTokenSpaceGuid.PcdSmbiosSystemRetailSku|"<Device_Model>_<Device_Codename>"
gQcomPkgTokenSpaceGuid.PcdSmbiosBoardModel|"<Device Model>"
# Simple FrameBuffer
gQcomPkgTokenSpaceGuid.PcdMipiFrameBufferWidth|<Display Width>
gQcomPkgTokenSpaceGuid.PcdMipiFrameBufferHeight|<Display Height>
gQcomPkgTokenSpaceGuid.PcdMipiFrameBufferColorDepth|<Display Color Depth>
# Dynamic RAM Start Address
gQcomPkgTokenSpaceGuid.PcdRamPartitionBase|<Free DDR Region Start Address>
# SD Card Slot
gQcomPkgTokenSpaceGuid.PcdSDCardSlotPresent|TRUE # If your Phone has no SD Card Slot, Set it to FALSE.
# USB Controller
gQcomPkgTokenSpaceGuid.PcdStartUsbController|TRUE # This should be TRUE unless your UsbConfigDxe is Patched to be Dual Role.
[PcdsDynamicDefault]
gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|<Display Width>
gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|<Display Height>
gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|<Display Width>
gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|<Display Height>
gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutColumn|<Setup Con Column>
gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow|<Setup Con Row>
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|<Con Column>
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|<Con Row>
!include <SoC Codename>Pkg/<SoC Codenmae>.dsc.inc
<GUID>
is a Value to identify your Device, Generate one here, Make sure its Uppercase.
<Start Address>
is the Start Address of the MemoryMap (uefiplat.cfg).
<CPU Vector Base Address>
is the Base Address of CPU Vectors
in the MemoryMap (uefiplat.cfg).
<UEFI Stack base/Size>
is the Base/Size Address of UEFI Stack
in the MemoryMap (uefiplat.cfg).
<Display Color Depth>
is the Value of your Display Color Depth, It can be Found in the Specs of your Phone, For Example on www.devicespecifications.com.
<Free DDR Region Start Address>
is the End Address of that Last DDR Memory Region. <Base Addr> + <Size Addr> = <End Addr>
.
<Setup Con Column> / <Con Column>
is the Value of <Display Width> / 8
.
<Setup Con Row> / <Con Row>
is the Value of <Display Height> / 19
.
After we created the .dsc File we will now continue now with the .dec File.
Create a File called <Device Codename>.dec
in Mu-Qcom/Platforms/<Device Vendor>/<Device Codename>/
.
Here is an template what it should contain:
[Defines]
DEC_SPECIFICATION = 0x00010005
PACKAGE_NAME = <Device Codename>
PACKAGE_GUID = <GUID>
PACKAGE_VERSION = 0.1
[Guids]
# NOTE: For these Values you need to use the GUID you generated earlier!
# These are just example Values.
g<Device Codename>TokenSpaceGuid = { 0x1ead32ce, 0x3165, 0x49eb, { 0xa9, 0x2d, 0xe8, 0x8a, 0x42, 0x57, 0x20, 0x02 } }
<GUID>
is the same GUID as in .dsc File.
Once the .dec File is complete we can move on to the .fdf File.
Create File called <Device Codename>.fdf
in Mu-Qcom/Platforms/<Device Vendor>/<Device Codename>/
.
The .fdf File contains Specific Stuff about your Device, Here is an template how it should look:
## @file
#
# Copyright (c) 2018, Linaro Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
################################################################################
#
# FD Section
# The [FD] Section is made up of the definition statements and a
# description of what goes into the Flash Device Image. Each FD section
# defines one flash "device" image. A flash device image may be one of
# the following: Removable media bootable image (like a boot floppy
# image,) an Option ROM image (that would be "flashed" into an add-in
# card,) a System "Flash" image (that would be burned into a system's
# flash) or an Update ("Capsule") image that will be used to update and
# existing system flash.
#
################################################################################
[FD.<Device Codename>_UEFI]
BaseAddress = $(FD_BASE)|gArmTokenSpaceGuid.PcdFdBaseAddress # The base address of the FLASH Device.
Size = $(FD_SIZE)|gArmTokenSpaceGuid.PcdFdSize # The size in bytes of the FLASH Device
ErasePolarity = 1
# This one is tricky, it must be: BlockSize * NumBlocks = Size
BlockSize = 0x1000
NumBlocks = $(FD_BLOCKS)
################################################################################
#
# Following are lists of FD Region layout which correspond to the locations of different
# images within the flash device.
#
# Regions must be defined in ascending order and may not overlap.
#
# A Layout Region start with a eight digit hex offset (leading "0x" required) followed by
# the pipe "|" character, followed by the size of the region, also in hex with the leading
# "0x" characters. Like:
# Offset|Size
# PcdOffsetCName|PcdSizeCName
# RegionType <FV, DATA, or FILE>
#
################################################################################
0x00000000|$(FD_SIZE)
gArmTokenSpaceGuid.PcdFvBaseAddress|gArmTokenSpaceGuid.PcdFvSize
FV = FVMAIN_COMPACT
################################################################################
#
# FV Section
#
# [FV] section is used to define what components or modules are placed within a flash
# device file. This section also defines order the components and modules are positioned
# within the image. The [FV] section consists of define statements, set statements and
# module statements.
#
################################################################################
[FV.FvMain]
FvNameGuid = 631008B0-B2D1-410A-8B49-2C5C4D8ECC7E
BlockSize = 0x1000
NumBlocks = 0 # This FV gets compressed so make it just big enough
FvAlignment = 8 # FV alignment and FV attributes setting.
ERASE_POLARITY = 1
MEMORY_MAPPED = TRUE
STICKY_WRITE = TRUE
LOCK_CAP = TRUE
LOCK_STATUS = TRUE
WRITE_DISABLED_CAP = TRUE
WRITE_ENABLED_CAP = TRUE
WRITE_STATUS = TRUE
WRITE_LOCK_CAP = TRUE
WRITE_LOCK_STATUS = TRUE
READ_DISABLED_CAP = TRUE
READ_ENABLED_CAP = TRUE
READ_STATUS = TRUE
READ_LOCK_CAP = TRUE
READ_LOCK_STATUS = TRUE
!include Include/APRIORI.inc
!include Include/DXE.inc
!include Include/RAW.inc
INF EmbeddedPkg/Drivers/VirtualKeyboardDxe/VirtualKeyboardDxe.inf
# BDS
INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
INF MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf
# ACPI and SMBIOS
INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
INF MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
INF <SoC Codename>Pkg/Drivers/SmBiosTableDxe/SmBiosTableDxe.inf
# ACPI Tables
!include Include/ACPI.inc
INF MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf
INF DfciPkg/IdentityAndAuthManager/IdentityAndAuthManagerDxe.inf
!include QcomPkg/Extra.fdf.inc
[FV.FVMAIN_COMPACT]
FvAlignment = 8
ERASE_POLARITY = 1
MEMORY_MAPPED = TRUE
STICKY_WRITE = TRUE
LOCK_CAP = TRUE
LOCK_STATUS = TRUE
WRITE_DISABLED_CAP = TRUE
WRITE_ENABLED_CAP = TRUE
WRITE_STATUS = TRUE
WRITE_LOCK_CAP = TRUE
WRITE_LOCK_STATUS = TRUE
READ_DISABLED_CAP = TRUE
READ_ENABLED_CAP = TRUE
READ_STATUS = TRUE
READ_LOCK_CAP = TRUE
READ_LOCK_STATUS = TRUE
INF QcomPkg/PrePi/PrePi.inf
FILE FREEFORM = dde58710-41cd-4306-dbfb-3fa90bb1d2dd {
SECTION UI = "uefiplat.cfg"
SECTION RAW = Binaries/<Device Codename>/RawFiles/uefiplat.cfg
}
FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE {
SECTION FV_IMAGE = FVMAIN
}
}
!include QcomPkg/Common.fdf.inc
Now we create some files for the .fdf
File
For Now, Leave it Empty, When your UEFI is working stable then you can Follow the ACPI Guide.
We continue with APRIORI.inc
, Create APRIORI.inc
in Mu-Qcom/Platforms/<Device Vendor>/<Device Codename>Pkg/Include/
.
Now we need the order of the Binaries in APRIORI.inc
, Use UEFITool to get the Order:
Next we place all the Binaries in APRIORI.inc
like this:
INF <Path to .inf File>
After you ordered and added all the Files you also need to add some extra stuff to APRIORI.inc
:
INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
INF ArmPkg/Drivers/ArmPsciMpServicesDxe/ArmPsciMpServicesDxe.inf
INF QcomPkg/Drivers/DynamicRAMDxe/DynamicRAMDxe.inf
INF QcomPkg/Drivers/ClockSpeedUpDxe/ClockSpeedUpDxe.inf
INF QcomPkg/Drivers/SimpleFbDxe/SimpleFbDxe.inf
Pcd
should be under DxeMain
.
ArmPsciMpServicesDxe
should be under TimerDxe
.
DynamicRAMDxe
should be under SmemDxe
.
ClockSpeedUpDxe
should be under ClockDxe
.
SimpleFbDxe
dosen't Replace DisplayDxe
Make an If case for it, Check other Devices for the if case.
Also make sure that you don't add FvSimpleFileSystemDxe
.
Check other Devices APRIORI.inc File to get an Idea, What to replace with the Mu Driver and what not.
After that we can now move on to DXE.inc
, Create DXE.inc
in Mu-Qcom/Platforms/<Device Vendor>/<Device Codename>Pkg/Include/
.
Now again we need the Order, To get the order of DXE.inc
Open xbl
or uefi
in UEFITool and Expand the FV(s), Then you see the Order.
Again we place all the Binaries like this:
INF <Path to .inf>
Also here again you need to add some extra Stuff:
INF ArmPkg/Drivers/ArmPsciMpServicesDxe/ArmPsciMpServicesDxe.inf
INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
INF QcomPkg/Drivers/DynamicRAMDxe/DynamicRAMDxe.inf
INF QcomPkg/Drivers/ClockSpeedUpDxe/ClockSpeedUpDxe.inf
INF QcomPkg/Drivers/SimpleFbDxe/SimpleFbDxe.inf
INF MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.inf
ArmPsciMpServicesDxe
should be under TimerDxe
.
Pcd
should be under DxeMain
.
DynamicRAMDxe
should be under SmemDxe
.
ClockSpeedUpDxe
should be under ClockDxe
.
SimpleFbDxe
dosen't Replace DisplayDxe
Make an If case for it, Check other Devices for the if case.
UsbMouseAbsolutePointerDxe
should be under UsbKbDxe
.
Remove any EFI Applications from XBL in DXE.inc
.
Also again, Make sure that you don't add FvSimpleFileSystemDxe
.
Check other Devices DXE.inc File to get an Idea, What to replace with the Mu Driver and what not.
You can take the RAW Files Order from DXE.inc that UEFIReader generated.
Thats how they should look:
FILE FREEFORM = <GUID> {
SECTION RAW = Binaries/<Device Codename>/RawFiles/<File Name>.<File Extension>
SECTION UI = "<Name>"
}
Just UEFIReader dosen't format the Lines correct, You need to Correct that.
Also Remove any RAW Section that has an Picture.
Now, We move on to creating a Configuration Map for your Device.
We need uefiplat.cfg from XBL to create This Map.
Here is an Template for the .c File:
#include <Library/BaseLib.h>
#include <Library/DeviceConfigurationMapLib.h>
STATIC
CONFIGURATION_DESCRIPTOR_EX
gDeviceConfigurationDescriptorEx[] = {
// NOTE: All Conf are located before Terminator!
// Terminator
{"Terminator", 0xFFFFFFFF}
};
CONFIGURATION_DESCRIPTOR_EX*
GetDeviceConfigurationMap ()
{
return gDeviceConfigurationDescriptorEx;
}
Place all Configs from [ConfigParameters]
(uefiplat.cfg) In the .c File.
Here is an Example:
EnableShell = 0x1
Becomes this:
{"EnableShell", 0x1},
Configs that have Strings instead of Decimal won't be added:
# This for Example
OsTypeString = "LA"
And don't add ConfigParameterCount
to the .c File either.
Lets move on making Memory Map.
We will use uefiplat.cfg to create the Memory Map.
Create a Folder Named DeviceMemoryMapLib
in Mu-Qcom/Platforms/<Device Vendor>/<Device Codename>Pkg/Library/
.
After that create two Files called DeviceMemoryMapLib.c
and DeviceMemoryMapLib.inf
.
Here is an template for the .c File:
STATIC
ARM_MEMORY_REGION_DESCRIPTOR_EX
gDeviceMemoryDescriptorEx[] = {
// Name, Address, Length, HobOption, ResourceAttribute, ArmAttributes, ResourceType, MemoryType
// DDR Regions
// Other memory regions
// Register regions
// Terminator for MMU
{"Terminator", 0, 0, 0, 0, 0, 0, 0}
};
ARM_MEMORY_REGION_DESCRIPTOR_EX*
GetDeviceMemoryMap ()
{
return gDeviceMemoryDescriptorEx;
}
Place all DDR
Memory Regions under DDR Regions
in DeviceMemoryMapLib.c
, Example:
0xEA600000, 0x02400000, "Display Reserved", AddMem, MEM_RES, SYS_MEM_CAP, Reserv, WRITE_THROUGH_XN
would become in the Memory Map:
{"Display Reserved", 0xEA600000, 0x02400000, AddMem, MEM_RES, SYS_MEM_CAP, Reserv, WRITE_THROUGH_XN},
Do that with every Memory Region but if an #
is infront of an Memory Region do not add it.
After that it should look something like this.
You also need to create a Script that creates the Boot Image.
You can Copy a Device with similear/Same Boot Image Creation Script and just replace the Code Name with yours.
If there is no Device with similear Boot Image Creation Script, Extract the Original Android Boot Image with AIK (Android Image Kitchen).
Then you just use the Info that the Tool Gives you and Put them into the Script.
Now Build your Device with:
./build_uefi.sh -d <Device Codename> -r DEBUG
There are too Many Cases for Errors in UEFI, So if you have any Please contact us on Discord.