build_bootloader.py 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. # Adds a platformio/Scons target to build the bootloader image.
  2. # It is basically a copy of the main firmware but using BlueSCSI_bootloader.cpp
  3. # as the main() function.
  4. import os
  5. Import("env")
  6. # Build a version of BlueSCSI_main.cpp that calls bootloader instead
  7. env2 = env.Clone()
  8. env2.Append(CPPFLAGS = "-DBlueSCSI_BOOTLOADER_MAIN")
  9. bootloader_main = env2.Object(
  10. os.path.join("$BUILD_DIR", "bootloader_main.o"),
  11. ["BlueSCSI_main.cpp"]
  12. )
  13. # Include all other dependencies except BlueSCSI_main.cpp
  14. dep_objs = []
  15. for nodelist in env["PIOBUILDFILES"]:
  16. for node in nodelist:
  17. filename = str(node.rfile())
  18. if 'BlueSCSI_main' not in filename:
  19. dep_objs.append(node)
  20. # print("Bootloader dependencies: ", type(dep_objs), str([str(f.rfile()) for f in dep_objs]))
  21. # Use different linker script for bootloader
  22. if env2.GetProjectOption("ldscript_bootloader"):
  23. env2.Replace(LDSCRIPT_PATH = env2.GetProjectOption("ldscript_bootloader"))
  24. env2['LINKFLAGS'] = [a for a in env2['LINKFLAGS'] if not a.startswith('-T') and not a.endswith('.ld')]
  25. env2.Append(LINKFLAGS="-T" + env2.GetProjectOption("ldscript_bootloader"))
  26. # Build bootloader.elf
  27. bootloader_elf = env2.Program(
  28. os.path.join("$BUILD_DIR", "bootloader.elf"),
  29. [bootloader_main] + dep_objs
  30. )
  31. # Strip bootloader symbols so that it can be combined with main program
  32. bootloader_bin = env.ElfToBin(
  33. os.path.join("$BUILD_DIR", "bootloader.bin"),
  34. bootloader_elf
  35. )
  36. # Convert back to .o to facilitate linking
  37. def escape_cpp(path):
  38. '''Apply double-escaping for path name to include in generated C++ file'''
  39. result = ''
  40. for c in str(path).encode('utf-8'):
  41. if 32 <= c <= 127 and c not in (ord('\\'), ord('"')):
  42. result += chr(c)
  43. else:
  44. result += '\\\\%03o' % c
  45. return result
  46. temp_src = env.subst(os.path.join("$BUILD_DIR", "bootloader_bin.cpp"))
  47. open(temp_src, 'w').write(
  48. '''
  49. __asm__(
  50. " .section .text.btldr\\n"
  51. "btldr:\\n"
  52. " .incbin \\"%s\\"\\n"
  53. );
  54. ''' % escape_cpp(bootloader_bin[0])
  55. )
  56. bootloader_obj = env.Object(
  57. os.path.join("$BUILD_DIR", "bootloader_bin.o"),
  58. temp_src
  59. )
  60. # Add bootloader binary as dependency to the main firmware
  61. main_fw = os.path.join("$BUILD_DIR", env.subst("$PROGNAME$PROGSUFFIX"))
  62. env.Depends(bootloader_obj, bootloader_bin)
  63. env.Depends(main_fw, bootloader_obj)
  64. env.Append(LINKFLAGS = [bootloader_obj])