test_bootloader.py 4.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. # SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
  2. # SPDX-License-Identifier: Apache-2.0
  3. import logging
  4. import shutil
  5. from pathlib import Path
  6. from typing import Union
  7. from test_build_system_helpers import EnvDict, IdfPyFunc, bin_file_contains, file_contains, replace_in_file
  8. def get_two_header_bytes(file_path: Union[str, Path]) -> str:
  9. '''
  10. get the bytes 3-4 of the given file
  11. https://docs.espressif.com/projects/esptool/en/latest/esp32/advanced-topics/firmware-image-format.html
  12. '''
  13. data = b''
  14. with open(file_path, 'rb') as f:
  15. data = f.read(4)
  16. extracted_bytes = data[2:4]
  17. return extracted_bytes.hex()
  18. def test_bootloader_custom_overrides_original(test_app_copy: Path, idf_py: IdfPyFunc, default_idf_env: EnvDict) -> None:
  19. logging.info('Custom bootloader overrides original')
  20. idf_path = Path(default_idf_env.get('IDF_PATH'))
  21. shutil.copytree(idf_path / 'components' / 'bootloader', test_app_copy / 'components' / 'bootloader')
  22. # Because of relative include of Kconfig, also esp_bootloader_format needs to be copied.
  23. shutil.copytree(idf_path / 'components' / 'esp_bootloader_format', test_app_copy / 'components' / 'esp_bootloader_format')
  24. idf_py('bootloader')
  25. assert file_contains(test_app_copy / 'build' / 'bootloader' / 'compile_commands.json',
  26. str(test_app_copy / 'components' / 'bootloader' / 'subproject' / 'main' / 'bootloader_start.c'))
  27. def test_bootloader_custom_ignores_extra_component(test_app_copy: Path, idf_py: IdfPyFunc, default_idf_env: EnvDict) -> None:
  28. logging.info('Custom bootloader can ignore extra components')
  29. idf_path = Path(default_idf_env.get('IDF_PATH'))
  30. # Import the main bootloader component that overrides the default one
  31. shutil.copytree(idf_path / 'examples' / 'custom_bootloader' / 'bootloader_override' / 'bootloader_components',
  32. test_app_copy / 'bootloader_components')
  33. # Compile it normally and make sure the bootloader is overridden for now
  34. idf_py('bootloader')
  35. # Search for 'Custom bootloader message defined in the KConfig file.' in the resulting binary
  36. # which is the default value for EXAMPLE_BOOTLOADER_WELCOME_MESSAGE Kconfig option.
  37. default_message = bytes('Custom bootloader message defined in the KConfig file.', 'ascii')
  38. assert bin_file_contains(test_app_copy / 'build' / 'bootloader' / 'bootloader.bin', default_message)
  39. # Clean the project
  40. idf_py('fullclean')
  41. # Ignore bootloader component and rebuild
  42. replace_in_file(test_app_copy / 'CMakeLists.txt',
  43. '# placeholder_after_include_project_cmake',
  44. 'set(BOOTLOADER_IGNORE_EXTRA_COMPONENT "main")')
  45. idf_py('bootloader')
  46. # The overridden message must not be present anymore
  47. assert not bin_file_contains(test_app_copy / 'build' / 'bootloader' / 'bootloader.bin', default_message)
  48. def test_bootloader_correctly_set_image_header(test_app_copy: Path, idf_py: IdfPyFunc) -> None:
  49. logging.info('Flash size is correctly set in the bootloader image header')
  50. # Build with the default 2MB setting
  51. idf_py('bootloader')
  52. assert get_two_header_bytes(test_app_copy / 'build' / 'bootloader' / 'bootloader.bin') == '0210'
  53. # Change to 4MB
  54. (test_app_copy / 'sdkconfig').write_text('CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y')
  55. idf_py('reconfigure', 'bootloader')
  56. assert get_two_header_bytes(test_app_copy / 'build' / 'bootloader' / 'bootloader.bin') == '0220'
  57. # Change to QIO, bootloader should still be DIO (will change to QIO in 2nd stage bootloader)
  58. (test_app_copy / 'sdkconfig').write_text('CONFIG_FLASHMODE_QIO=y')
  59. idf_py('reconfigure', 'bootloader')
  60. assert get_two_header_bytes(test_app_copy / 'build' / 'bootloader' / 'bootloader.bin') == '0210'
  61. # Change to 80 MHz
  62. (test_app_copy / 'sdkconfig').write_text('CONFIG_ESPTOOLPY_FLASHFREQ_80M=y')
  63. idf_py('reconfigure', 'bootloader')
  64. assert get_two_header_bytes(test_app_copy / 'build' / 'bootloader' / 'bootloader.bin') == '021f'