You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							166 lines
						
					
					
						
							4.5 KiB
						
					
					
				
			
		
		
	
	
							166 lines
						
					
					
						
							4.5 KiB
						
					
					
				import os
 | 
						|
import opendbc
 | 
						|
import subprocess
 | 
						|
 | 
						|
PREFIX = "arm-none-eabi-"
 | 
						|
BUILDER = "DEV"
 | 
						|
 | 
						|
common_flags = []
 | 
						|
 | 
						|
if os.getenv("RELEASE"):
 | 
						|
  BUILD_TYPE = "RELEASE"
 | 
						|
  cert_fn = os.getenv("CERT")
 | 
						|
  assert cert_fn is not None, 'No certificate file specified. Please set CERT env variable'
 | 
						|
  assert os.path.exists(cert_fn), 'Certificate file not found. Please specify absolute path'
 | 
						|
else:
 | 
						|
  BUILD_TYPE = "DEBUG"
 | 
						|
  cert_fn = File("./certs/debug").srcnode().relpath
 | 
						|
  common_flags += ["-DALLOW_DEBUG"]
 | 
						|
 | 
						|
  if os.getenv("DEBUG"):
 | 
						|
    common_flags += ["-DDEBUG"]
 | 
						|
 | 
						|
def objcopy(source, target, env, for_signature):
 | 
						|
    return '$OBJCOPY -O binary %s %s' % (source[0], target[0])
 | 
						|
 | 
						|
def get_version(builder, build_type):
 | 
						|
  try:
 | 
						|
    git = subprocess.check_output(["git", "rev-parse", "--short=8", "HEAD"], encoding='utf8').strip()
 | 
						|
  except subprocess.CalledProcessError:
 | 
						|
    git = "unknown"
 | 
						|
  return f"{builder}-{git}-{build_type}"
 | 
						|
 | 
						|
def get_key_header(name):
 | 
						|
  from Crypto.PublicKey import RSA
 | 
						|
 | 
						|
  public_fn = File(f'./certs/{name}.pub').srcnode().get_path()
 | 
						|
  with open(public_fn) as f:
 | 
						|
    rsa = RSA.importKey(f.read())
 | 
						|
  assert(rsa.size_in_bits() == 1024)
 | 
						|
 | 
						|
  rr = pow(2**1024, 2, rsa.n)
 | 
						|
  n0inv = 2**32 - pow(rsa.n, -1, 2**32)
 | 
						|
 | 
						|
  r = [
 | 
						|
    f"RSAPublicKey {name}_rsa_key = {{",
 | 
						|
    f"  .len = 0x20,",
 | 
						|
    f"  .n0inv = {n0inv}U,",
 | 
						|
    f"  .n = {to_c_uint32(rsa.n)},",
 | 
						|
    f"  .rr = {to_c_uint32(rr)},",
 | 
						|
    f"  .exponent = {rsa.e},",
 | 
						|
    f"}};",
 | 
						|
  ]
 | 
						|
  return r
 | 
						|
 | 
						|
def to_c_uint32(x):
 | 
						|
  nums = []
 | 
						|
  for _ in range(0x20):
 | 
						|
    nums.append(x % (2**32))
 | 
						|
    x //= (2**32)
 | 
						|
  return "{" + 'U,'.join(map(str, nums)) + "U}"
 | 
						|
 | 
						|
 | 
						|
def build_project(project_name, project, main, extra_flags):
 | 
						|
  project_dir = Dir(f'./board/obj/{project_name}/')
 | 
						|
 | 
						|
  flags = project["FLAGS"] + extra_flags + common_flags + [
 | 
						|
    "-Wall",
 | 
						|
    "-Wextra",
 | 
						|
    "-Wstrict-prototypes",
 | 
						|
    "-Werror",
 | 
						|
    "-mlittle-endian",
 | 
						|
    "-mthumb",
 | 
						|
    "-nostdlib",
 | 
						|
    "-fno-builtin",
 | 
						|
    "-std=gnu11",
 | 
						|
    "-fmax-errors=1",
 | 
						|
    f"-T{File(project['LINKER_SCRIPT']).srcnode().relpath}",
 | 
						|
    "-fsingle-precision-constant",
 | 
						|
    "-Os",
 | 
						|
    "-g",
 | 
						|
  ]
 | 
						|
 | 
						|
  env = Environment(
 | 
						|
    ENV=os.environ,
 | 
						|
    CC=PREFIX + 'gcc',
 | 
						|
    AS=PREFIX + 'gcc',
 | 
						|
    OBJCOPY=PREFIX + 'objcopy',
 | 
						|
    OBJDUMP=PREFIX + 'objdump',
 | 
						|
    OBJPREFIX=project_dir,
 | 
						|
    CFLAGS=flags,
 | 
						|
    ASFLAGS=flags,
 | 
						|
    LINKFLAGS=flags,
 | 
						|
    CPPPATH=[Dir("./"), "./board/stm32h7/inc", opendbc.INCLUDE_PATH],
 | 
						|
    ASCOM="$AS $ASFLAGS -o $TARGET -c $SOURCES",
 | 
						|
    BUILDERS={
 | 
						|
      'Objcopy': Builder(generator=objcopy, suffix='.bin', src_suffix='.elf')
 | 
						|
    },
 | 
						|
    tools=["default", "compilation_db"],
 | 
						|
  )
 | 
						|
 | 
						|
  startup = env.Object(project["STARTUP_FILE"])
 | 
						|
 | 
						|
  # Build bootstub
 | 
						|
  bs_env = env.Clone()
 | 
						|
  bs_env.Append(CFLAGS="-DBOOTSTUB", ASFLAGS="-DBOOTSTUB", LINKFLAGS="-DBOOTSTUB")
 | 
						|
  bs_elf = bs_env.Program(f"{project_dir}/bootstub.elf", [
 | 
						|
    startup,
 | 
						|
    "./crypto/rsa.c",
 | 
						|
    "./crypto/sha.c",
 | 
						|
    "./board/bootstub.c",
 | 
						|
  ])
 | 
						|
  bs_env.Objcopy(f"./board/obj/bootstub.{project_name}.bin", bs_elf)
 | 
						|
 | 
						|
  # Build + sign main (aka app)
 | 
						|
  main_elf = env.Program(f"{project_dir}/main.elf", [
 | 
						|
    startup,
 | 
						|
    main
 | 
						|
  ], LINKFLAGS=[f"-Wl,--section-start,.isr_vector={project['APP_START_ADDRESS']}"] + flags)
 | 
						|
  main_bin = env.Objcopy(f"{project_dir}/main.bin", main_elf)
 | 
						|
  sign_py = File(f"./crypto/sign.py").srcnode().relpath
 | 
						|
  env.Command(f"./board/obj/{project_name}.bin.signed", main_bin, f"SETLEN=1 {sign_py} $SOURCE $TARGET {cert_fn}")
 | 
						|
 | 
						|
 | 
						|
 | 
						|
base_project_h7 = {
 | 
						|
  "STARTUP_FILE": "./board/stm32h7/startup_stm32h7x5xx.s",
 | 
						|
  "LINKER_SCRIPT": "./board/stm32h7/stm32h7x5_flash.ld",
 | 
						|
  "APP_START_ADDRESS": "0x8020000",
 | 
						|
  "FLAGS": [
 | 
						|
    "-mcpu=cortex-m7",
 | 
						|
    "-mhard-float",
 | 
						|
    "-DSTM32H7",
 | 
						|
    "-DSTM32H725xx",
 | 
						|
    "-Iboard/stm32h7/inc",
 | 
						|
    "-mfpu=fpv5-d16",
 | 
						|
  ],
 | 
						|
}
 | 
						|
 | 
						|
# Common autogenerated includes
 | 
						|
with open("board/obj/gitversion.h", "w") as f:
 | 
						|
  version = get_version(BUILDER, BUILD_TYPE)
 | 
						|
  f.write(f'extern const uint8_t gitversion[{len(version)}];\n')
 | 
						|
  f.write(f'const uint8_t gitversion[{len(version)}] = "{version}";\n')
 | 
						|
 | 
						|
with open("board/obj/version", "w") as f:
 | 
						|
  f.write(f'{get_version(BUILDER, BUILD_TYPE)}')
 | 
						|
 | 
						|
certs = [get_key_header(n) for n in ["debug", "release"]]
 | 
						|
with open("board/obj/cert.h", "w") as f:
 | 
						|
  for cert in certs:
 | 
						|
    f.write("\n".join(cert) + "\n")
 | 
						|
 | 
						|
# panda fw
 | 
						|
build_project("panda_h7", base_project_h7, "./board/main.c", [])
 | 
						|
 | 
						|
# panda jungle fw
 | 
						|
flags = [
 | 
						|
  "-DPANDA_JUNGLE",
 | 
						|
]
 | 
						|
if os.getenv("FINAL_PROVISIONING"):
 | 
						|
  flags += ["-DFINAL_PROVISIONING"]
 | 
						|
build_project("panda_jungle_h7", base_project_h7, "./board/jungle/main.c", flags)
 | 
						|
 | 
						|
# test files
 | 
						|
if GetOption('extras'):
 | 
						|
  SConscript('tests/libpanda/SConscript')
 | 
						|
 |