Skip to content

Instantly share code, notes, and snippets.

@sunflower2333
Last active November 30, 2025 08:19
Show Gist options
  • Select an option

  • Save sunflower2333/f93ec07e6f981e0ff30d5f87ab6aefe0 to your computer and use it in GitHub Desktop.

Select an option

Save sunflower2333/f93ec07e6f981e0ff30d5f87ab6aefe0 to your computer and use it in GitHub Desktop.
This program help your parse your uefiplat to C code.
from pyfdt.pyfdt import FdtBlobParse
# NOTICE, you need to install pyfdt package first :)
# pip install pyfdt
SIZE_2GB = 0x80000000
class MemoryDescriptor:
# base = 0
# size = 0
# label = ""
# build_hob = ""
# resource_type = ""
# resource_attribute = ""
# mem_type = ""
# cache_attributes = ""
def __init__(self, label, base, size, build_hob, resource_type, resource_attribute, mem_type, cache_attributes):
self.label = str(label)
self.base = int(base, 16)
self.size = int(size, 16)
self.build_hob = str(build_hob)
self.resource_type = str(resource_type)
self.resource_attribute = str(resource_attribute)
self.mem_type = str(mem_type)
self.cache_attributes = str(cache_attributes)
def region2msg(self):
msg = '{' + self.label + "0x%08X" % self.base + ', ' + "0x%08X" % self.size + ',' + self.build_hob \
+ ',' + self.resource_type + ',' + self.resource_attribute + ',' + self.mem_type + ',' \
+ self.cache_attributes + ' },'
return msg
class DDRBank:
def __init__(self, base, size):
self.base = base
self.size = size
def ddr_bank_to_msg(self):
msg = "/* RAM Entry: Base 0x%016X\tSize 0x%016X" % (self.base, self.size) + " */"
return msg
def check_if_locate_in_bank(self, descriptor) -> bool:
# err_msg = "WARNING: descriptor region is invalid: \n"
# desc_info = "base: " + str(descriptor.base) + ", \t size:" + str(descriptor.size)
# err_cases = {
# "base_not_in_range_err": "The provided memory region's base address is not located in ddr regions.\n",
# "big_size_error": "The provided memory region's size if bigger than ddr size.\n",
# "oversize_error": "The provided memory region is greater than ddr region.\n"
# }
# if descriptor.base < self.base:
# print(err_msg + err_cases["base_not_in_range_err"] + desc_info)
# # raise MemoryError(err_msg + err_cases["base_not_in_range_err"] + desc_info)
# if descriptor.size > self.size:
# print(err_msg + err_cases["base_not_in_range_err"] + desc_info)
# # raise MemoryError(err_msg + err_cases["big_size_error"] + desc_info)
# if descriptor.base + descriptor.size > self.base + self.size:
# print(err_msg + err_cases["base_not_in_range_err"] + desc_info)
# # raise MemoryError(err_msg + err_cases["oversize_error"] + desc_info)
return (descriptor.base + descriptor.size <= self.base + self.size) and (descriptor.base >= self.base)
def generate_conv_region(base, size):
conv_region = MemoryDescriptor(" \"RAM Partition\", ", "0x0", "0x0", " AddMem", " SYS_MEM",
" SYS_MEM_CAP", " Conv", " WRITE_BACK_XN")
conv_region.base = base
conv_region.size = size
return conv_region
def parse_memory_line_to_msg(line):
if line[-1] == '\n':
line = line[0:-1]
mem_base, mem_size, mem_label, build_hob, \
resource_type, resource_attribute, memory_type, cache_attributes = line.split(',')
mem_label+=','
# Sort Code
space_count = build_hob.count(' ')
build_hob = build_hob[(space_count - 1):]
mem_label = mem_label + space_count * ' '
# print C code
msg = '{' + mem_label + mem_base + ',' + mem_size + ',' + build_hob \
+ ',' + resource_type + ',' + resource_attribute + ',' + memory_type + ',' + cache_attributes + '},'
return msg
# Parse memory part in uefiplat.cfg, then return the memory descriptor.
def parse_memory_line_to_object(line):
if line[-1] == '\n':
line = line[0:-1]
mem_base, mem_size, mem_label, build_hob, \
resource_type, resource_attribute, memory_type, cache_attributes = line.split(',')
# Sort Code
space_count = build_hob.count(' ')
build_hob = build_hob[(space_count - 1):]
mem_label = mem_label + ',' + space_count * ' '
return MemoryDescriptor(mem_label, mem_base, mem_size, build_hob, resource_type, resource_attribute, memory_type,
cache_attributes)
# Check Overlap in a sorted memory region descriptor array.
def overlap_checker(in_descriptors):
descriptors = in_descriptors.copy()
# Firstly, sorted this array by region base
descriptors.sort(key=lambda d: d.base)
# Secondly, check overlap.
overlap_flag = False
last_desc = descriptors[0]
descriptors.pop(0)
for desc in descriptors:
if last_desc.base + last_desc.size > desc.base:
print("WARNING!!! Overlap Detected!")
print("last_descriptor:\n\tbase: " + str(last_desc.base) + ",\tsize: " + str(last_desc.size))
print("current_descriptor:\n\tbase: " + str(desc.base) + ",\tsize: " + str(desc.size))
overlap_flag = True
continue
last_desc = desc
continue
if overlap_flag:
raise MemoryError("Please Check Your Uefiplat.cfg !!!")
# Check if there are memory gaps in given ddr bank and memory descriptors.
def gap_checker(ddr_regions, in_descriptors):
# backup descriptors
result = in_descriptors.copy()
descriptors = in_descriptors.copy()
# Insure descriptors array is sorted.
descriptors.sort(key=lambda d: d.base)
# Firstly, check if all regions is valid.
for desc in descriptors:
available_flag = False
for ddr_bank in ddr_regions:
if ddr_bank.check_if_locate_in_bank(desc):
available_flag = True
if not available_flag:
desc_info = "base: " + hex(desc.base) + ", \t size:" + hex(desc.size)
print("// WARNING: gap_checker failed. Unknown error happen." + desc_info)
# raise MemoryError("gap_checker failed. Unknown error happen.")
# Secondly, check if there are gaps near regions
last_desc = descriptors[0]
descriptors.pop(0)
for desc in descriptors:
if last_desc.base + last_desc.size < desc.base:
# Fill conventional regions here.
# 1, Calculate conv region base and size.
conv_region = generate_conv_region(last_desc.base + last_desc.size,
desc.base - (last_desc.base + last_desc.size))
# 2. Check if conv region available in DDR banks.
for ddr_bank in ddr_regions:
if not ddr_bank.check_if_locate_in_bank(last_desc):
continue
if not ddr_bank.check_if_locate_in_bank(conv_region):
conv_region.size = (ddr_bank.base + ddr_bank.size) - conv_region.base
if conv_region.size:
result.append(conv_region)
last_desc = desc
# Finally, sorted the array before returning.
result.sort(key=lambda d: d.base)
return result
# Parse the config part in uefiplat.cfg, then return the c code.
def parse_config_line(line):
if line[-1] == '\n':
line = line[0:-1]
config_name, config_value = line.split(' = ')
msg = '{\"' + config_name + '\", ' + config_value + '},\n'
if config_value[0] == '\"':
msg = ''
return msg
# This function will split a memory region which is greater than 2GB into 2GB pieces in a list.
def split_region(descriptor):
result = []
tmp_size = descriptor.size
tmp_base = descriptor.base
while tmp_size >= SIZE_2GB:
result.append(generate_conv_region(tmp_base, SIZE_2GB))
tmp_size -= SIZE_2GB
tmp_base += SIZE_2GB
if tmp_size:
result.append(generate_conv_region(tmp_base, tmp_size))
return result
# In this function, all the unmapped memory in
# ddr bank will be filled be conventional system memory.
def ddr_filler(ddr_regions, in_descriptor):
descriptor = in_descriptor.copy()
# Make sure the array is sorted.
descriptor.sort(key=lambda d: d.base)
# Firstly, find the last region and all unmapped banks.
passed_banks_flag = False
for ddr_region in ddr_regions:
if not passed_banks_flag:
if not ddr_region.check_if_locate_in_bank(descriptor[-1]):
continue
# if (descriptor[-1].base + descriptor[-1].size) == (ddr_region.base + ddr_region.size):
# continue
passed_banks_flag = True
descriptor += split_region(generate_conv_region(descriptor[-1].base + descriptor[-1].size,
(ddr_region.base + ddr_region.size) - (
descriptor[-1].base + descriptor[-1].size)))
else:
# Secondly, split and fill the rest parts
descriptor += split_region(generate_conv_region(ddr_region.base, ddr_region.size))
return descriptor
def find_cells_by_reg(path, cells_name, obj_fdt):
cells_val = 1
folders = path.split('/')
folders.pop(-1)
for f in reversed(folders):
if None is not obj_fdt.resolve_path(path + cells_name):
cells_val = obj_fdt.resolve_path(path + cells_name)[0]
return cells_val
if f != '':
path = path.removesuffix(f + '/')
return cells_val # Not found
def regs_to_ddr_banks_by_cells(this_addr_cells, this_size_cells, this_regs):
this_ddr_banks = []
# [addr, size, addr, size, ...]
for i in range(0, len(this_regs), this_addr_cells + this_size_cells):
if this_addr_cells == 1:
this_ddr_banks.append(
DDRBank(this_regs[i],
this_regs[i + 1] if this_size_cells == 1 else (this_regs[i + 1] << 32) + this_regs[i + 2]))
if this_addr_cells == 2:
this_ddr_banks.append(DDRBank((this_regs[i] << 32) + this_regs[i + 1],
this_regs[i + 2] if this_size_cells == 1 else
(this_regs[i + 2] << 32) + this_regs[i + 3]))
return this_ddr_banks
if __name__ == "__main__":
uefi_plat_file_path = "./uefiplat.cfg"
fdt_file_path = "./fdt"
pFile = open(uefi_plat_file_path, "r", encoding="utf-8")
pFDT = open(fdt_file_path, "rb")
this_line = "value" # mustn't be none here
# Get DDR Banks from FDT
fdt = FdtBlobParse(pFDT).to_fdt()
mem_reg_path = "/memory/reg/"
addr_cells = find_cells_by_reg(mem_reg_path, "#address-cells", fdt)
size_cells = find_cells_by_reg(mem_reg_path, "#size-cells", fdt)
ddr_banks = regs_to_ddr_banks_by_cells(addr_cells, size_cells, fdt.resolve_path(mem_reg_path))
ddr_banks.sort(key=lambda d: d.base)
for bank in ddr_banks:
print(bank.ddr_bank_to_msg())
# Find [MemoryMap]
while this_line != "[MemoryMap]\n":
this_line = pFile.readline()
if this_line == '': # EOF
print("Invalid uefiplat.cfg")
break
if this_line[0] == '#': # Pass comment
continue
# Parse [MemoryMap]
regions = []
while True:
this_line = pFile.readline()
if this_line == '' or this_line[0] == '[':
break
if this_line[0] == '\n' or this_line[0] == '#' and this_line[0:2] != '#-':
continue
if this_line[0:2] == '#-':
this_line = "//" + this_line[1:]
print(this_line)
continue
regions.append(parse_memory_line_to_object(this_line))
# Sort regions by memory base.
regions.sort(key=lambda r: r.base)
# Check for overlap.
overlap_checker(regions)
# Find and fill memory gaps between regions
regions = gap_checker(ddr_banks, regions)
# Fill the reset of spaces in ddr bank with conventional regions.
regions = ddr_filler(ddr_banks, regions)
for region in regions:
print(region.region2msg())
# Find [RegisterMap]
while this_line != "[RegisterMap]\n":
this_line = pFile.readline()
if this_line == '': # EOF
print("Invalid UefiCfg")
break
if this_line[0] == '#': # Pass comment
continue
# Parse [RegisterMap]
while True:
this_line = pFile.readline()
if this_line == '' or this_line[0] == '[':
break
if this_line[0] == '\n' or this_line[0] == '#' and this_line[0:2] != '#-':
continue
if this_line[0:2] == '#-':
this_line = "//" + this_line[1:]
print(this_line)
continue
print(parse_memory_line_to_msg(this_line))
# print("\n// Configuration Map")
#
# Find [ConfigParameters]
# while this_line != "[ConfigParameters]\n":
# this_line = pFile.readline()
# if this_line == '': # EOF
# print("Invalid UefiCfg")
# break
# if this_line[0] == '#': # Pass comment
# continue
#
# # Parse [ConfigParameters]
# while True:
# this_line = pFile.readline()
# if this_line == '' or this_line[0] == '[':
# break
# if this_line[0] == '\n' or this_line[0] == '#':
# continue
# print(parse_config_line(this_line), end='')
pFile.close()
pFDT.close()
@sunflower2333
Copy link
Author

sunflower2333 commented May 14, 2023

It will print memory map you need and configuration map you need.

You need to run pip install pyfdt before run this script.
Ensure there is a file named fdt and a file named uefiplat.cfg under the working folder.

Example:

/* RAM Entry: Base 0x0000000080000000   Size 0x0000000000E00000 */
/* RAM Entry: Base 0x00000000811D0000   Size 0x0000000056F90000 */
/* RAM Entry: Base 0x00000000D8800000   Size 0x0000000000000000 */
/* RAM Entry: Base 0x00000000E1BB0000   Size 0x000000001E450000 */
/* RAM Entry: Base 0x0000000880000000   Size 0x0000000038700000 */
/* RAM Entry: Base 0x00000008C0000000   Size 0x0000000140000000 */
/* RAM Entry: Base 0x0000000A00000000   Size 0x0000000200000000 */
//--------------------- DDR  -----

// WARNING: gap_checker failed. Unknown error happen.base: 0x80000000,   size:0x1200000
// WARNING: gap_checker failed. Unknown error happen.base: 0xd8800000,   size:0x7400000
{ "NOMAP",             0x80000000,0x01200000, NoMap,  MEM_RES, UNCACHEABLE, Reserv, UNCACHED_UNBUFFERED_XN },
{ "RSRV0",             0x81200000,0x00800000, AddMem, SYS_MEM, SYS_MEM_CAP, Reserv, WRITE_BACK_XN },
{ "XBL DT",            0x81A00000,0x00040000, AddMem, SYS_MEM, SYS_MEM_CAP, Reserv, WRITE_BACK_XN },
{ "XBL Ramdump",       0x81A40000,0x001C0000, AddMem, MEM_RES, UNCACHEABLE, Reserv, UNCACHED_UNBUFFERED_XN },
{ "AOP",               0x81C00000,0x000A0000, AddMem, MEM_RES, UNCACHEABLE, Reserv, UNCACHED_UNBUFFERED_XN },
{ "RAM Partition",     0x81CA0000,0x00060000, AddMem, SYS_MEM, SYS_MEM_CAP, Conv, WRITE_BACK_XN },
{ "SMEM",              0x81D00000,0x00200000, AddMem, MEM_RES, UNCACHEABLE, Reserv, UNCACHED_UNBUFFERED_XN },
{ "RAM Partition",     0x81F00000,0x08900000, AddMem, SYS_MEM, SYS_MEM_CAP, Conv, WRITE_BACK_XN },
{ "PIL Reserved",      0x8A800000,0x18280000, AddMem, MEM_RES, UNCACHEABLE, Reserv, UNCACHED_UNBUFFERED_XN },
{ "Display Demura",    0xA2A80000,0x02B00000, AddMem, MEM_RES, SYS_MEM_CAP, Reserv, WRITE_THROUGH_XN },
{ "RAM Partition",     0xA5580000,0x00B80000, AddMem, SYS_MEM, SYS_MEM_CAP, Conv, WRITE_BACK_XN },
{ "DBI Dump",          0xA6100000,0x00F00000, NoHob,  MMAP_IO, INITIALIZED, Conv,   UNCACHED_UNBUFFERED_XN },
{ "UEFI FD",           0xA7000000,0x00400000, AddMem, SYS_MEM, SYS_MEM_CAP, BsData, WRITE_BACK },
{ "UEFI FD Reserved",  0xA7400000,0x00200000, AddMem, SYS_MEM, SYS_MEM_CAP, BsData, WRITE_BACK },
{ "CPU Vectors",       0xA7600000,0x00001000, AddMem, SYS_MEM, SYS_MEM_CAP, BsData, WRITE_BACK },
{ "Info Blk",          0xA7601000,0x00001000, AddMem, SYS_MEM, SYS_MEM_CAP, RtData, WRITE_BACK_XN },
{ "MMU PageTables",    0xA7602000,0x00003000, AddMem, SYS_MEM, SYS_MEM_CAP, BsData, WRITE_BACK_XN   },
{ "Log Buffer",        0xA7605000,0x00008000, AddMem, SYS_MEM, SYS_MEM_CAP, RtData, WRITE_BACK_XN       },
{ "UEFI Stack",        0xA760D000,0x00040000, AddMem, SYS_MEM, SYS_MEM_CAP, BsData, WRITE_BACK_XN },
{ "SEC Heap",          0xA764D000,0x0008C000, AddMem, SYS_MEM, SYS_MEM_CAP, BsData, WRITE_BACK_XN },
{ "Sched Heap",        0xA76D9000,0x00400000, AddMem, SYS_MEM, SYS_MEM_CAP, BsData, WRITE_BACK_XN },
{ "FV Region",         0xA7AD9000,0x00400000, AddMem, SYS_MEM, SYS_MEM_CAP, BsData, WRITE_BACK_XN },
{ "UEFI RESV",         0xA7ED9000,0x00127000, AddMem, SYS_MEM, SYS_MEM_CAP, BsData, WRITE_BACK_XN },
{ "Kernel",            0xA8000000,0x10000000, AddMem, SYS_MEM, SYS_MEM_CAP, Reserv, WRITE_BACK_XN },
{ "Display Reserved",  0xB8000000,0x02B00000, AddMem, MEM_RES, SYS_MEM_CAP, Reserv, WRITE_THROUGH_XN },
{ "DXE Heap",          0xBAB00000,0x0D1C0000, AddMem, SYS_MEM, SYS_MEM_CAP, Conv,   WRITE_BACK_XN },
{ "RAM Partition",     0xC7CC0000,0x104A0000, AddMem, SYS_MEM, SYS_MEM_CAP, Conv, WRITE_BACK_XN },
{ "TZApps Reserved",   0xD8800000,0x07400000, AddDynamicMem, MEM_RES, UNCACHEABLE, Reserv, UNCACHED_UNBUFFERED_XN },
{ "RAM Partition",     0xDFC00000,0x1FC00000, AddMem, SYS_MEM, SYS_MEM_CAP, Conv, WRITE_BACK_XN },
{ "NOMAP",             0xFF800000,0x00800000, NoMap,  MEM_RES, UNCACHEABLE, Reserv, UNCACHED_UNBUFFERED_XN },
{ "RAM Partition",     0x880000000,0x38700000, AddMem, SYS_MEM, SYS_MEM_CAP, Conv, WRITE_BACK_XN },
{ "RAM Partition",     0x8C0000000,0x80000000, AddMem, SYS_MEM, SYS_MEM_CAP, Conv, WRITE_BACK_XN },
{ "RAM Partition",     0x940000000,0x80000000, AddMem, SYS_MEM, SYS_MEM_CAP, Conv, WRITE_BACK_XN },
{ "RAM Partition",     0x9C0000000,0x40000000, AddMem, SYS_MEM, SYS_MEM_CAP, Conv, WRITE_BACK_XN },
{ "RAM Partition",     0xA00000000,0x80000000, AddMem, SYS_MEM, SYS_MEM_CAP, Conv, WRITE_BACK_XN },
{ "RAM Partition",     0xA80000000,0x80000000, AddMem, SYS_MEM, SYS_MEM_CAP, Conv, WRITE_BACK_XN },
{ "RAM Partition",     0xB00000000,0x80000000, AddMem, SYS_MEM, SYS_MEM_CAP, Conv, WRITE_BACK_XN },
{ "RAM Partition",     0xB80000000,0x80000000, AddMem, SYS_MEM, SYS_MEM_CAP, Conv, WRITE_BACK_XN },
//--------------------- Other -----

{ "IMEM Base"          ,0x14680000, 0x0002A000, NoHob,  MMAP_IO, INITIALIZED, Conv,   NS_DEVICE},
{ "IMEM Cookie Base"   ,0x146AA000, 0x00016000, AddDev, MMAP_IO, INITIALIZED, Conv,   NS_DEVICE},
//--------------------- Register --

{ "IPC_ROUTER_TOP"     ,0x00400000, 0x00100000, AddDev, MMAP_IO, UNCACHEABLE, MmIO,   NS_DEVICE},
{ "SECURITY CONTROL"   ,0x00780000, 0x00007000, AddDev, MMAP_IO, UNCACHEABLE, MmIO,   NS_DEVICE},
{ "QUP"                ,0x00800000, 0x00300000, AddDev, MMAP_IO, UNCACHEABLE, MmIO,   NS_DEVICE},
{ "PRNG_CFG_PRNG"      ,0x010C0000, 0x0000C000, AddDev, MMAP_IO, UNCACHEABLE, MmIO,   NS_DEVICE},
{ "CRYPTO0 CRYPTO"     ,0x01DC0000, 0x00040000, AddDev, MMAP_IO, UNCACHEABLE, MmIO,   NS_DEVICE},
{ "CORE_TOP_CSR"       ,0x01F00000, 0x00100000, AddDev, MMAP_IO, UNCACHEABLE, MmIO,   NS_DEVICE},
{ "PERIPH_SS"          ,0x08800000, 0x00100000, AddDev, MMAP_IO, UNCACHEABLE, MmIO,   NS_DEVICE},
{ "USB"                ,0x0A600000, 0x00200000, AddDev, MMAP_IO, UNCACHEABLE, MmIO,   NS_DEVICE},
{ "AOSS"               ,0x0B000000, 0x04000000, AddDev, MMAP_IO, UNCACHEABLE, MmIO,   NS_DEVICE},
{ "TLMM"               ,0x0F000000, 0x01000000, AddDev, MMAP_IO, UNCACHEABLE, MmIO,   NS_DEVICE},
{ "SMMU"               ,0x15000000, 0x00200000, AddDev, MMAP_IO, UNCACHEABLE, MmIO,   NS_DEVICE},
{ "APSS_HM"            ,0x17000000, 0x02000000, AddDev, MMAP_IO, UNCACHEABLE, MmIO,   NS_DEVICE},

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment