Skip to content

Latest commit

 

History

History
570 lines (466 loc) · 20.5 KB

Device.md

File metadata and controls

570 lines (466 loc) · 20.5 KB

Adding Devices

Description

This Guide will show you how to create an UEFI Port for your Device.

WARNING

Booting Windows/Linux on Sony/Google Device will wipe your UFS Clean! (Unable to recover)

Table of Contents

Requirements

To Port UEFI to your Phone, It needs the following things:

  • An Snapdragon SoC
  • xbl or uefi 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.

Copying Files (Step 1)

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.

Creating the Config File (Step 2)

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.

Creating Files (Step 3)

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

Creating .dsc & .dec & .fdf File (Step 3.1)

Creating .dsc File (Step 3.1.1)

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.

Creating .dec File (Step 3.1.2)

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.

Creating .fdf File (Step 3.1.3)

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

Creating .fdf.inc Files (Step 3.2)

Now we create some files for the .fdf File

Creating ACPI.inc (Step 3.2.1)

For Now, Leave it Empty, When your UEFI is working stable then you can Follow the ACPI Guide.

Creating APRIORI.inc (Step 3.2.2)

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:

Preview Preview

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.

Creating DXE.inc File (Step 3.2.3)

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.

Creating RAW.inc (Step 3.2.4)

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.

Creating DeviceConfigurationMap Library (Step 3.3)

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.

Creating DeviceMemoryMap Library (Step 3.4)

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.

Creating Android Boot Image Script (Step 3.5)

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.

Building

Now Build your Device with:

./build_uefi.sh -d <Device Codename> -r DEBUG

Troubleshooting

There are too Many Cases for Errors in UEFI, So if you have any Please contact us on Discord.