utils.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. # SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  2. # SPDX-License-Identifier: Apache-2.0
  3. import argparse
  4. import binascii
  5. import os
  6. import uuid
  7. from typing import List, Optional, Tuple
  8. from construct import Int16ul
  9. def crc32(input_values: List[int], crc: int) -> int:
  10. """
  11. Name Polynomial Reversed? Init-value XOR-out
  12. crc32 0x104C11DB7 True 4294967295 (UINT32_MAX) 0xFFFFFFFF
  13. """
  14. return binascii.crc32(bytearray(input_values), crc)
  15. def required_clusters_count(cluster_size: int, content: bytes) -> int:
  16. # compute number of required clusters for file text
  17. return (len(content) + cluster_size - 1) // cluster_size
  18. def generate_4bytes_random() -> int:
  19. return uuid.uuid4().int & 0xFFFFFFFF
  20. def pad_string(content: str, size: Optional[int] = None, pad: int = 0x20) -> str:
  21. # cut string if longer and fill with pad character if shorter than size
  22. return content.ljust(size or len(content), chr(pad))[:size]
  23. def split_to_name_and_extension(full_name: str) -> Tuple[str, str]:
  24. name, extension = os.path.splitext(full_name)
  25. return name, extension.replace('.', '')
  26. def is_valid_fatfs_name(string: str) -> bool:
  27. return string == string.upper()
  28. def split_by_half_byte_12_bit_little_endian(value: int) -> Tuple[int, int, int]:
  29. value_as_bytes = Int16ul.build(value)
  30. return value_as_bytes[0] & 0x0f, value_as_bytes[0] >> 4, value_as_bytes[1] & 0x0f
  31. def build_byte(first_half: int, second_half: int) -> int:
  32. return (first_half << 4) | second_half
  33. def clean_first_half_byte(bytes_array: bytearray, address: int) -> None:
  34. """
  35. the function sets to zero first four bits of the byte.
  36. E.g. 10111100 -> 10110000
  37. """
  38. bytes_array[address] &= 0xf0
  39. def clean_second_half_byte(bytes_array: bytearray, address: int) -> None:
  40. """
  41. the function sets to zero last four bits of the byte.
  42. E.g. 10111100 -> 00001100
  43. """
  44. bytes_array[address] &= 0x0f
  45. def split_content_into_sectors(content: bytes, sector_size: int) -> List[bytes]:
  46. result = []
  47. clusters_cnt = required_clusters_count(cluster_size=sector_size, content=content)
  48. for i in range(clusters_cnt):
  49. result.append(content[sector_size * i:(i + 1) * sector_size])
  50. return result
  51. def get_args_for_partition_generator(desc: str) -> argparse.Namespace:
  52. parser = argparse.ArgumentParser(
  53. description=desc)
  54. parser.add_argument('input_directory',
  55. help='Path to the directory that will be encoded into fatfs image')
  56. parser.add_argument('--output_file',
  57. default='fatfs_image.img',
  58. help='Filename of the generated fatfs image')
  59. parser.add_argument('--partition_size',
  60. default=1024 * 1024,
  61. help='Size of the partition in bytes')
  62. parser.add_argument('--sector_size',
  63. default=4096,
  64. help='Size of the partition in bytes')
  65. args = parser.parse_args()
  66. if not os.path.isdir(args.input_directory):
  67. raise NotADirectoryError(f'The target directory `{args.input_directory}` does not exist!')
  68. return args