openubmc-bingo 0.5.240__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of openubmc-bingo might be problematic. Click here for more details.

Files changed (242) hide show
  1. bmcgo/__init__.py +12 -0
  2. bmcgo/bmcgo.py +22 -0
  3. bmcgo/bmcgo_config.py +176 -0
  4. bmcgo/cli/__init__.py +10 -0
  5. bmcgo/cli/cli.py +584 -0
  6. bmcgo/codegen/__init__.py +14 -0
  7. bmcgo/codegen/c/__init__.py +9 -0
  8. bmcgo/codegen/c/annotation.py +52 -0
  9. bmcgo/codegen/c/argument.py +42 -0
  10. bmcgo/codegen/c/codegen.py +153 -0
  11. bmcgo/codegen/c/comment.py +22 -0
  12. bmcgo/codegen/c/ctype_defination.py +353 -0
  13. bmcgo/codegen/c/helper.py +87 -0
  14. bmcgo/codegen/c/interface.py +63 -0
  15. bmcgo/codegen/c/method.py +82 -0
  16. bmcgo/codegen/c/property.py +180 -0
  17. bmcgo/codegen/c/renderer.py +21 -0
  18. bmcgo/codegen/c/signal.py +64 -0
  19. bmcgo/codegen/c/template/client.c.mako +145 -0
  20. bmcgo/codegen/c/template/client.h.mako +36 -0
  21. bmcgo/codegen/c/template/interface.c.mako +0 -0
  22. bmcgo/codegen/c/template/interface.introspect.xml.mako +99 -0
  23. bmcgo/codegen/c/template/micro_component.c.mako +32 -0
  24. bmcgo/codegen/c/template/public.c.mako +228 -0
  25. bmcgo/codegen/c/template/public.h.mako +128 -0
  26. bmcgo/codegen/c/template/server.c.mako +104 -0
  27. bmcgo/codegen/c/template/server.h.mako +36 -0
  28. bmcgo/codegen/lua/.lua-format +7 -0
  29. bmcgo/codegen/lua/Makefile +101 -0
  30. bmcgo/codegen/lua/__init__.py +9 -0
  31. bmcgo/codegen/lua/codegen.py +171 -0
  32. bmcgo/codegen/lua/proto/Makefile +87 -0
  33. bmcgo/codegen/lua/proto/ipmi_types.proto +17 -0
  34. bmcgo/codegen/lua/proto/types.proto +52 -0
  35. bmcgo/codegen/lua/script/check_intfs.py +161 -0
  36. bmcgo/codegen/lua/script/dto/__init__.py +11 -0
  37. bmcgo/codegen/lua/script/dto/exception.py +53 -0
  38. bmcgo/codegen/lua/script/dto/kepler_abstract.py +47 -0
  39. bmcgo/codegen/lua/script/dto/options.py +33 -0
  40. bmcgo/codegen/lua/script/dto/print_simple.py +19 -0
  41. bmcgo/codegen/lua/script/dto/redfish_api.py +241 -0
  42. bmcgo/codegen/lua/script/dto/url_route.py +195 -0
  43. bmcgo/codegen/lua/script/gen_db_json.py +444 -0
  44. bmcgo/codegen/lua/script/gen_depends.py +89 -0
  45. bmcgo/codegen/lua/script/gen_entry.py +263 -0
  46. bmcgo/codegen/lua/script/gen_feature_json.py +156 -0
  47. bmcgo/codegen/lua/script/gen_historical_local_db_json.py +88 -0
  48. bmcgo/codegen/lua/script/gen_intf_json.py +261 -0
  49. bmcgo/codegen/lua/script/gen_intf_rpc_json.py +575 -0
  50. bmcgo/codegen/lua/script/gen_ipmi_json.py +485 -0
  51. bmcgo/codegen/lua/script/gen_mdb_json.py +117 -0
  52. bmcgo/codegen/lua/script/gen_rpc_msg_json.py +487 -0
  53. bmcgo/codegen/lua/script/gen_schema.py +302 -0
  54. bmcgo/codegen/lua/script/ipmi_types_pb2.py +135 -0
  55. bmcgo/codegen/lua/script/loader/__init__.py +11 -0
  56. bmcgo/codegen/lua/script/loader/file_utils.py +33 -0
  57. bmcgo/codegen/lua/script/loader/kepler_abstract_collect.py +79 -0
  58. bmcgo/codegen/lua/script/loader/kepler_abstract_loader.py +47 -0
  59. bmcgo/codegen/lua/script/loader/redfish_loader.py +127 -0
  60. bmcgo/codegen/lua/script/lua_format.py +62 -0
  61. bmcgo/codegen/lua/script/mds_util.py +385 -0
  62. bmcgo/codegen/lua/script/merge_model.py +330 -0
  63. bmcgo/codegen/lua/script/merge_proto_algo.py +85 -0
  64. bmcgo/codegen/lua/script/proto_loader.py +47 -0
  65. bmcgo/codegen/lua/script/proto_plugin.py +140 -0
  66. bmcgo/codegen/lua/script/redfish_source_tree.py +118 -0
  67. bmcgo/codegen/lua/script/render_utils/__init__.py +38 -0
  68. bmcgo/codegen/lua/script/render_utils/base.py +25 -0
  69. bmcgo/codegen/lua/script/render_utils/client_lua.py +98 -0
  70. bmcgo/codegen/lua/script/render_utils/controller_lua.py +71 -0
  71. bmcgo/codegen/lua/script/render_utils/db_lua.py +224 -0
  72. bmcgo/codegen/lua/script/render_utils/error_lua.py +185 -0
  73. bmcgo/codegen/lua/script/render_utils/factory.py +52 -0
  74. bmcgo/codegen/lua/script/render_utils/ipmi_lua.py +159 -0
  75. bmcgo/codegen/lua/script/render_utils/ipmi_message_lua.py +24 -0
  76. bmcgo/codegen/lua/script/render_utils/mdb_lua.py +177 -0
  77. bmcgo/codegen/lua/script/render_utils/mdb_register.py +215 -0
  78. bmcgo/codegen/lua/script/render_utils/message_lua.py +26 -0
  79. bmcgo/codegen/lua/script/render_utils/messages_lua.py +156 -0
  80. bmcgo/codegen/lua/script/render_utils/model_lua.py +485 -0
  81. bmcgo/codegen/lua/script/render_utils/old_model_lua.py +429 -0
  82. bmcgo/codegen/lua/script/render_utils/plugin_lua.py +38 -0
  83. bmcgo/codegen/lua/script/render_utils/redfish_proto.py +86 -0
  84. bmcgo/codegen/lua/script/render_utils/request_lua.py +76 -0
  85. bmcgo/codegen/lua/script/render_utils/service_lua.py +130 -0
  86. bmcgo/codegen/lua/script/render_utils/utils_message_lua.py +125 -0
  87. bmcgo/codegen/lua/script/render_utils/validate_lua.py +221 -0
  88. bmcgo/codegen/lua/script/sep_ipmi_message_cmds.py +217 -0
  89. bmcgo/codegen/lua/script/template.py +166 -0
  90. bmcgo/codegen/lua/script/types_pb2.py +516 -0
  91. bmcgo/codegen/lua/script/utils.py +663 -0
  92. bmcgo/codegen/lua/script/validate.py +80 -0
  93. bmcgo/codegen/lua/script/yaml_to_json.py +73 -0
  94. bmcgo/codegen/lua/templates/Makefile +114 -0
  95. bmcgo/codegen/lua/templates/apps/Makefile +261 -0
  96. bmcgo/codegen/lua/templates/apps/Makefile.mdb.mk +64 -0
  97. bmcgo/codegen/lua/templates/apps/app.lua.mako +19 -0
  98. bmcgo/codegen/lua/templates/apps/class.lua.mako +35 -0
  99. bmcgo/codegen/lua/templates/apps/client.lua.mako +429 -0
  100. bmcgo/codegen/lua/templates/apps/controller.lua.mako +276 -0
  101. bmcgo/codegen/lua/templates/apps/datas.lua.mako +8 -0
  102. bmcgo/codegen/lua/templates/apps/db.lua.mako +89 -0
  103. bmcgo/codegen/lua/templates/apps/entry.lua.mako +128 -0
  104. bmcgo/codegen/lua/templates/apps/feature.lua.mako +37 -0
  105. bmcgo/codegen/lua/templates/apps/generate_route.mako +25 -0
  106. bmcgo/codegen/lua/templates/apps/impl_feature.lua.mako +72 -0
  107. bmcgo/codegen/lua/templates/apps/ipmi.lua.mako +97 -0
  108. bmcgo/codegen/lua/templates/apps/ipmi_cmd.lua.mako +18 -0
  109. bmcgo/codegen/lua/templates/apps/ipmi_message.lua.mako +36 -0
  110. bmcgo/codegen/lua/templates/apps/local_db.lua.mako +263 -0
  111. bmcgo/codegen/lua/templates/apps/main.lua.mako +25 -0
  112. bmcgo/codegen/lua/templates/apps/mc.lua.mako +77 -0
  113. bmcgo/codegen/lua/templates/apps/mdb.lua.mako +45 -0
  114. bmcgo/codegen/lua/templates/apps/mdb_interface.lua.mako +73 -0
  115. bmcgo/codegen/lua/templates/apps/message.lua.mako +38 -0
  116. bmcgo/codegen/lua/templates/apps/model.lua.mako +239 -0
  117. bmcgo/codegen/lua/templates/apps/orm_classes.lua.mako +16 -0
  118. bmcgo/codegen/lua/templates/apps/plugin.lua.mako +8 -0
  119. bmcgo/codegen/lua/templates/apps/redfish.proto.mako +47 -0
  120. bmcgo/codegen/lua/templates/apps/service.lua.mako +440 -0
  121. bmcgo/codegen/lua/templates/apps/signal_listen.lua.mako +19 -0
  122. bmcgo/codegen/lua/templates/apps/utils/default_intf.lua.mako +41 -0
  123. bmcgo/codegen/lua/templates/apps/utils/enum.mako +10 -0
  124. bmcgo/codegen/lua/templates/apps/utils/imports.mako +13 -0
  125. bmcgo/codegen/lua/templates/apps/utils/mdb_intf.lua.mako +25 -0
  126. bmcgo/codegen/lua/templates/apps/utils/mdb_obj.lua.mako +23 -0
  127. bmcgo/codegen/lua/templates/apps/utils/message.mako +160 -0
  128. bmcgo/codegen/lua/templates/apps/utils/request.lua.mako +59 -0
  129. bmcgo/codegen/lua/templates/apps/utils/validate.mako +83 -0
  130. bmcgo/codegen/lua/templates/errors.lua.mako +36 -0
  131. bmcgo/codegen/lua/templates/messages.lua.mako +32 -0
  132. bmcgo/codegen/lua/templates/new_app/.clang-format.mako +170 -0
  133. bmcgo/codegen/lua/templates/new_app/.gitignore.mako +26 -0
  134. bmcgo/codegen/lua/templates/new_app/CHANGELOG.md.mako +0 -0
  135. bmcgo/codegen/lua/templates/new_app/CMakeLists.txt.mako +29 -0
  136. bmcgo/codegen/lua/templates/new_app/Makefile.mako +25 -0
  137. bmcgo/codegen/lua/templates/new_app/README.md.mako +0 -0
  138. bmcgo/codegen/lua/templates/new_app/conanfile.py.mako +7 -0
  139. bmcgo/codegen/lua/templates/new_app/config.cfg.mako +6 -0
  140. bmcgo/codegen/lua/templates/new_app/mds/model.json.mako +3 -0
  141. bmcgo/codegen/lua/templates/new_app/mds/service.json.mako +21 -0
  142. bmcgo/codegen/lua/templates/new_app/permissions.ini.mako +16 -0
  143. bmcgo/codegen/lua/templates/new_app/src/lualib/${project_name}_app.lua.mako +16 -0
  144. bmcgo/codegen/lua/templates/new_app/src/service/main.lua.mako +25 -0
  145. bmcgo/codegen/lua/templates/new_app/test/integration/test_${project_name}.conf.mako +9 -0
  146. bmcgo/codegen/lua/templates/new_app/test/integration/test_${project_name}.lua.mako +47 -0
  147. bmcgo/codegen/lua/templates/new_app/test/unit/test.lua.mako +23 -0
  148. bmcgo/codegen/lua/templates/new_app/user_conf/rootfs/etc/systemd/system/${project_name}.service.mako +18 -0
  149. bmcgo/codegen/lua/templates/new_app/user_conf/rootfs/etc/systemd/system/multi-user.target.wants/${project_name}.service.link +1 -0
  150. bmcgo/component/__init__.py +10 -0
  151. bmcgo/component/analysis/analysis.py +183 -0
  152. bmcgo/component/analysis/build_deps.py +165 -0
  153. bmcgo/component/analysis/data_deps.py +333 -0
  154. bmcgo/component/analysis/dep-rules.json +912 -0
  155. bmcgo/component/analysis/dep_node.py +110 -0
  156. bmcgo/component/analysis/intf_deps.py +163 -0
  157. bmcgo/component/analysis/intf_validation.py +254 -0
  158. bmcgo/component/analysis/rule.py +211 -0
  159. bmcgo/component/analysis/smc_dfx_whitelist.json +11 -0
  160. bmcgo/component/analysis/sr_validation.py +391 -0
  161. bmcgo/component/build.py +222 -0
  162. bmcgo/component/component_dt_version_parse.py +348 -0
  163. bmcgo/component/component_helper.py +114 -0
  164. bmcgo/component/coverage/__init__.py +11 -0
  165. bmcgo/component/coverage/c_incremental_cov_report.template +53 -0
  166. bmcgo/component/coverage/incremental_cov.py +464 -0
  167. bmcgo/component/deploy.py +110 -0
  168. bmcgo/component/gen.py +169 -0
  169. bmcgo/component/package_info.py +236 -0
  170. bmcgo/component/template/conanbase.py.mako +278 -0
  171. bmcgo/component/template/conanfile.deploy.py.mako +40 -0
  172. bmcgo/component/test.py +947 -0
  173. bmcgo/errors.py +119 -0
  174. bmcgo/frame.py +217 -0
  175. bmcgo/functional/__init__.py +10 -0
  176. bmcgo/functional/analysis.py +96 -0
  177. bmcgo/functional/bmc_studio_action.py +98 -0
  178. bmcgo/functional/check.py +185 -0
  179. bmcgo/functional/conan_index_build.py +251 -0
  180. bmcgo/functional/config.py +332 -0
  181. bmcgo/functional/csr_build.py +724 -0
  182. bmcgo/functional/deploy.py +263 -0
  183. bmcgo/functional/diff.py +235 -0
  184. bmcgo/functional/fetch.py +235 -0
  185. bmcgo/functional/full_component.py +391 -0
  186. bmcgo/functional/maintain.py +381 -0
  187. bmcgo/functional/new.py +166 -0
  188. bmcgo/functional/schema_valid.py +111 -0
  189. bmcgo/functional/simple_sign.py +104 -0
  190. bmcgo/functional/upgrade.py +78 -0
  191. bmcgo/ipmigen/__init__.py +13 -0
  192. bmcgo/ipmigen/ctype_defination.py +82 -0
  193. bmcgo/ipmigen/ipmigen.py +309 -0
  194. bmcgo/ipmigen/template/cmd.c.mako +366 -0
  195. bmcgo/ipmigen/template/ipmi.c.mako +25 -0
  196. bmcgo/ipmigen/template/ipmi.h.mako +51 -0
  197. bmcgo/logger.py +176 -0
  198. bmcgo/misc.py +117 -0
  199. bmcgo/target/app.yml +17 -0
  200. bmcgo/target/install_sdk.yml +15 -0
  201. bmcgo/target/personal.yml +53 -0
  202. bmcgo/target/publish.yml +45 -0
  203. bmcgo/tasks/__init__.py +11 -0
  204. bmcgo/tasks/download_buildtools_hm.py +124 -0
  205. bmcgo/tasks/misc.py +15 -0
  206. bmcgo/tasks/task.py +354 -0
  207. bmcgo/tasks/task_build_conan.py +714 -0
  208. bmcgo/tasks/task_build_rootfs_img.py +595 -0
  209. bmcgo/tasks/task_buildgppbin.py +88 -0
  210. bmcgo/tasks/task_buildhpm_ext4.py +82 -0
  211. bmcgo/tasks/task_create_interface_config.py +122 -0
  212. bmcgo/tasks/task_download_buildtools.py +99 -0
  213. bmcgo/tasks/task_download_dependency.py +72 -0
  214. bmcgo/tasks/task_hpm_envir_prepare.py +112 -0
  215. bmcgo/tasks/task_packet_to_supporte.py +87 -0
  216. bmcgo/tasks/task_prepare.py +105 -0
  217. bmcgo/tasks/task_sign_and_pack_hpm.py +42 -0
  218. bmcgo/utils/__init__.py +10 -0
  219. bmcgo/utils/buffer.py +128 -0
  220. bmcgo/utils/combine_json_schemas.py +170 -0
  221. bmcgo/utils/component_post.py +54 -0
  222. bmcgo/utils/component_version_check.py +86 -0
  223. bmcgo/utils/config.py +1067 -0
  224. bmcgo/utils/fetch_component_code.py +232 -0
  225. bmcgo/utils/install_manager.py +61 -0
  226. bmcgo/utils/installations/__init__.py +10 -0
  227. bmcgo/utils/installations/base_installer.py +70 -0
  228. bmcgo/utils/installations/install_consts.py +30 -0
  229. bmcgo/utils/installations/install_plans/bingo.yml +11 -0
  230. bmcgo/utils/installations/install_workflow.py +50 -0
  231. bmcgo/utils/installations/installers/apt_installer.py +177 -0
  232. bmcgo/utils/installations/installers/pip_installer.py +46 -0
  233. bmcgo/utils/installations/version_util.py +100 -0
  234. bmcgo/utils/mapping_config_patch.py +443 -0
  235. bmcgo/utils/perf_analysis.py +114 -0
  236. bmcgo/utils/tools.py +704 -0
  237. bmcgo/worker.py +417 -0
  238. openubmc_bingo-0.5.240.dist-info/METADATA +30 -0
  239. openubmc_bingo-0.5.240.dist-info/RECORD +242 -0
  240. openubmc_bingo-0.5.240.dist-info/WHEEL +5 -0
  241. openubmc_bingo-0.5.240.dist-info/entry_points.txt +2 -0
  242. openubmc_bingo-0.5.240.dist-info/top_level.txt +1 -0
@@ -0,0 +1,724 @@
1
+ #! /usr/bin/env python3
2
+ # encoding=utf-8
3
+ # 描述:CSR构建出包
4
+ # Copyright (c) 2024 Huawei Technologies Co., Ltd.
5
+ # openUBMC is licensed under Mulan PSL v2.
6
+ # You can use this software according to the terms and conditions of the Mulan PSL v2.
7
+ # You may obtain a copy of Mulan PSL v2 at:
8
+ # http://license.coscl.org.cn/MulanPSL2
9
+ # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
10
+ # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
11
+ # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
12
+ # See the Mulan PSL v2 for more details.
13
+
14
+ import os
15
+ import json
16
+ import time
17
+ import re
18
+ import argparse
19
+ import atexit
20
+ import shutil
21
+ import gzip
22
+ import io
23
+ import binascii
24
+ import hashlib
25
+ import tempfile
26
+ import subprocess
27
+ import configparser
28
+ from pathlib import Path
29
+ from datetime import datetime, timezone, timedelta
30
+ from bmcgo import misc
31
+ from bmcgo.logger import Logger
32
+ from bmcgo.misc import CommandInfo
33
+ from bmcgo.tasks.task import Task
34
+ from bmcgo.utils.tools import Tools
35
+ from bmcgo.utils.buffer import Buffer
36
+ from bmcgo.utils.config import Config
37
+ from bmcgo.bmcgo_config import BmcgoConfig
38
+
39
+ tool = Tools("build_csr")
40
+ log = tool.log
41
+ cwd = os.getcwd()
42
+
43
+ SR_UPGRADE = "SRUpgrade"
44
+ TIANCHI = "bmc.dev.Board.TianChi"
45
+ HPM_PACK_PATH = "/usr/share/bmcgo/csr_packet"
46
+ EEPROM_SIZE_LIMIT_CONFIG = "/usr/share/bmcgo/schema/eepromSizeLimit.json"
47
+
48
+ JSON_DATA_FORMAT = 0x01
49
+ SR_UID_MAX_LENGTH = 24
50
+ DEFAULT_EEPROM_SIZE_LIMIT = 32
51
+
52
+ # 需要兼容的组件UID列表
53
+ LEGACY_UIDS = [
54
+ "00000001050302023924", "00000001030302023925", "00000001040302023945",
55
+ "00000001040302023947", "00000001030302024340", "00000001030302023936",
56
+ "00000001030302023938", "00000001100302023955", "00000001100302023956",
57
+ "00000001040302052957", "00000001100302025549", "00000001030302023934"
58
+ ]
59
+
60
+
61
+ class CsrHeader:
62
+ def __init__(self, csr_head_len, csr_bytes_arr):
63
+ self.csr_max_count = 4
64
+ self.csr_ver = 0x01
65
+ self.padding = 0x0000
66
+ self.csr_count = 0
67
+ self.csr_offset = Buffer(self.csr_max_count * 2)
68
+ self.offset = csr_head_len // 8
69
+
70
+ for i in range(self.csr_max_count):
71
+ csr_bytes = csr_bytes_arr[i]
72
+ if csr_bytes:
73
+ self.csr_offset.put_uint16(self.offset)
74
+ self.offset += len(csr_bytes) // 8
75
+ self.csr_count += 1
76
+ else:
77
+ self.csr_offset.put_uint16(0x00)
78
+
79
+
80
+ class SrMakeOptions:
81
+ def __init__(self, comp_name: str, sr_json: dict, oem_data: bytearray):
82
+ self.comp_name = comp_name
83
+ self.sr_json = sr_json
84
+ self.oem_data = oem_data
85
+ self.uid = self.get_uid(sr_json)
86
+ self.binary_names = [self.uid]
87
+
88
+ def find_uid_from_object(self, parent, key, obj):
89
+ if key == TIANCHI:
90
+ if "UID" in obj:
91
+ return obj["UID"]
92
+ if "UID" in parent:
93
+ return parent["UID"]
94
+ for obj_key, value in obj.items():
95
+ if isinstance(value, dict):
96
+ ret = self.find_uid_from_object(obj, obj_key, value)
97
+ if ret:
98
+ return ret
99
+ return ""
100
+
101
+
102
+ def get_uid(self, sr_json):
103
+ component_id = ""
104
+ if "Objects" not in sr_json:
105
+ raise Exception(f"'Objects' not found in sr file")
106
+ objects = sr_json["Objects"]
107
+ for key in objects:
108
+ if re.fullmatch(r"SRUpgrade_\d", key):
109
+ if "UID" in objects[key]:
110
+ component_id = objects[key]["UID"]
111
+ break
112
+ if not component_id:
113
+ for key in objects:
114
+ ret = self.find_uid_from_object(objects, key, objects[key])
115
+ if ret:
116
+ component_id = ret
117
+ break
118
+ if not component_id:
119
+ raise Exception(f"未在{self.comp_name}文件中找到UID,没有UID的文件不支持出包。")
120
+ if len(component_id) > SR_UID_MAX_LENGTH:
121
+ raise Exception(f"{self.comp_name}文件UID超过最大长度,无法出包。")
122
+ return component_id
123
+
124
+
125
+ def if_available(bconfig: BmcgoConfig):
126
+ return (
127
+ bconfig.component is None and bconfig.conan_index is None and
128
+ bconfig.manifest is None
129
+ )
130
+
131
+ command_info: CommandInfo = CommandInfo(
132
+ group=misc.GRP_MISC,
133
+ name="build",
134
+ description=["CSR构建出包"],
135
+ hidden=False
136
+ )
137
+
138
+
139
+ class BmcgoCommand:
140
+ def __init__(self, bconfig: BmcgoConfig, *args):
141
+ self.bconfig = bconfig
142
+ parser = argparse.ArgumentParser(
143
+ prog="bingo build_csr",
144
+ description="csr出包,支持单个CSR和批量CSR出包",
145
+ add_help=True,
146
+ formatter_class=argparse.RawTextHelpFormatter
147
+ )
148
+ parser.add_argument("-s", "--single", help="指定单个CSR文件出包,默认为批量出包", action=misc.STORE_TRUE, default=False)
149
+ parser.add_argument("-p", "--path", help="单CSR出包时指定CSR文件路径,批量出包时指定CSR文件和OEM文件所在铺\n默认为当前路径", default=cwd)
150
+ parser.add_argument("-o", "--output_path", help="构建产物(hpm包或tar.gz压缩包)路径\n默认为当前路径", default=cwd)
151
+ parser.add_argument("--oem", help="单CSR出包携带OEM文件的路径,仅在--single模式下有效", default=None)
152
+ parser.add_argument("--hpm", help="单CSR出包生成hpm文件,仅在--single模式下有效", action=misc.STORE_TRUE, default=False)
153
+ parser.add_argument("-b", "--bin", help="单CSR出包生成bin文件的路径,仅在--single模式下有效",
154
+ action=misc.STORE_TRUE, default=False)
155
+ parser.add_argument("-u", "--uid", help="指定UID生成二进制文件,多个uid以','分隔,仅在--single模式下有效", default=None)
156
+ parser.add_argument("-f", "--frud", help="指定打包frud文件,跳过白名单校验", action=misc.STORE_TRUE, default=False)
157
+ parser.add_argument("-a", "--all", help="快捷携带-j、-b、--hpm参数,仅在--single模式下有效",
158
+ action=misc.STORE_TRUE, default=False)
159
+ parser.add_argument(
160
+ "-j",
161
+ "--json",
162
+ help="单CSR出包生成json文件,仅在--single模式下有效",
163
+ action=misc.STORE_TRUE,
164
+ default=False
165
+ )
166
+ parser.add_argument(
167
+ "-m",
168
+ "--max_config",
169
+ help="设定eeprom大小限制的json配置文件路径,无配置时默认限制为32k," +
170
+ "key为字符串类型,指定不带后缀的csr文件名称,value为数值类型,指定大小限制,单位KB",
171
+ default=EEPROM_SIZE_LIMIT_CONFIG
172
+ )
173
+ parsed_args, _ = parser.parse_known_args(*args)
174
+ self.csr_path = os.path.realpath(parsed_args.path)
175
+ self.single = parsed_args.single
176
+ self.oem_path = parsed_args.oem
177
+ self.output_path = os.path.realpath(parsed_args.output_path)
178
+ self.json = parsed_args.json
179
+ self.bin = parsed_args.bin
180
+ self.hpm = parsed_args.hpm
181
+ self.all = parsed_args.all
182
+ self.frud = parsed_args.frud
183
+ self.max_size_map = parsed_args.max_config
184
+ self.uid = parsed_args.uid
185
+ self.work_dir = None
186
+ self.target_dir = None
187
+
188
+ @staticmethod
189
+ def get_oem_data(dir_path: str, comp_name: str):
190
+ oem_file = f'oem_{comp_name}.bin'
191
+ oem_data = bytearray()
192
+ if os.path.exists(oem_file):
193
+ with open(oem_file, 'rb') as f:
194
+ oem_data = bytearray(f.read())
195
+ return oem_data
196
+
197
+ @staticmethod
198
+ def check_uid(options_list):
199
+ bin_names = set()
200
+ for options in options_list:
201
+ for name in options.binary_names:
202
+ if name in bin_names:
203
+ raise Exception(f"存在重复的 UID: {name},出包失败!")
204
+ bin_names.add(name)
205
+
206
+ @staticmethod
207
+ def is_valid_json_path(path_str):
208
+ if path_str == EEPROM_SIZE_LIMIT_CONFIG:
209
+ return True
210
+ path = Path(path_str)
211
+ basic_check = path.is_file() and path.suffix.lower() == '.json'
212
+ if not basic_check:
213
+ return False
214
+ try:
215
+ with open(path, 'r', encoding='utf-8-sig') as json_file:
216
+ json.load(json_file)
217
+ return True
218
+ except (json.JSONDecodeError, UnicodeDecodeError, IOError):
219
+ return False
220
+
221
+ def make_sr_binary(self, options: SrMakeOptions, hpm_temp_dir: str, max_size: int):
222
+ eeprom_build_controller = EepromBuild(self.bconfig, options, self.work_dir)
223
+ eeprom_data = eeprom_build_controller.build_eeprom()
224
+ if len(eeprom_data) > max_size * 1024 - 40:
225
+ raise Exception(f"Eeprom二进制文件大小超过限制:{options.comp_name}")
226
+ binary_files = []
227
+ for name in options.binary_names:
228
+ binary_files.append(os.path.join(hpm_temp_dir, f"{name}.bin"))
229
+ if self.bin or self.all:
230
+ log.info(f"生成{name}.bin文件...")
231
+ binary_files.append(os.path.join(self.target_dir, f"{name}.bin"))
232
+ if self.uid:
233
+ uid_list = str(self.uid).split(',')
234
+ for uid in uid_list:
235
+ log.info(f"生成{uid}.bin文件...")
236
+ binary_files.append(os.path.join(self.target_dir, f"{uid}.bin"))
237
+ if name not in LEGACY_UIDS and not self.frud:
238
+ continue
239
+ binary_files.append(os.path.join(hpm_temp_dir, f"{name}.frud"))
240
+ log.info(f"生成{name}.frud文件...")
241
+ if self.bin or self.all or self.frud:
242
+ binary_files.append(os.path.join(self.target_dir, f"{name}.frud"))
243
+ with open(binary_files[0], 'wb') as f:
244
+ f.write(eeprom_data)
245
+ for binary_file in binary_files[1:]:
246
+ shutil.copy(binary_files[0], binary_file)
247
+
248
+ def run(self):
249
+ self.check_args()
250
+ if not os.path.exists(self.output_path):
251
+ raise Exception(f"输出路径{self.output_path}不存在")
252
+ sr_make_options_list = []
253
+ if self.single:
254
+ sr_make_options_list = self.get_sr_file_and_oem()
255
+ else:
256
+ sr_make_options_list = self.get_sr_files()
257
+ if len(sr_make_options_list) == 0:
258
+ log.info("目录下不存在sr文件!")
259
+ return
260
+ log.info("进行SR文件UID唯一性验证...")
261
+ self.check_uid(sr_make_options_list)
262
+ try:
263
+ self.work_dir = tempfile.TemporaryDirectory().name
264
+ self.target_dir = os.path.join(self.work_dir, "target")
265
+ os.makedirs(self.target_dir, exist_ok=True)
266
+ hpm_temp_dir = os.path.join(self.work_dir, "hpm_temp")
267
+ os.makedirs(hpm_temp_dir, exist_ok=True)
268
+ self.make_eeprom(hpm_temp_dir, sr_make_options_list)
269
+ if not self.single or self.hpm or self.all:
270
+ if len(sr_make_options_list) == 1:
271
+ hpm_file = os.path.join(self.target_dir, f"{sr_make_options_list[0].comp_name}.hpm")
272
+ else:
273
+ hpm_file = os.path.join(self.target_dir, f"CSR-{get_timestamp()}.hpm")
274
+ hpm_package = HpmBuild(self.bconfig, hpm_file, self.work_dir)
275
+ log.info("开始执行hpm包构建任务...")
276
+ hpm_package.run()
277
+ if self.single or self.frud:
278
+ output_file = os.path.join(self.output_path, f"bingo-{get_timestamp()}.tar.gz")
279
+ tar_command = ['tar', '-czf', output_file, "-C", self.target_dir, "."]
280
+ try:
281
+ result = subprocess.run(tar_command, check=True)
282
+ log.info(f"成功创建压缩包{os.path.basename(output_file)}")
283
+ except subprocess.CalledProcessError as e:
284
+ log.info(f"创建压缩包时出错,错误原因:{str(e)}")
285
+ else:
286
+ output_hpm_file = os.path.join(self.output_path, os.path.basename(hpm_file))
287
+ shutil.copy(hpm_file, output_hpm_file)
288
+ log.info("构建成功!")
289
+ finally:
290
+ if os.path.exists(self.work_dir):
291
+ shutil.rmtree(self.work_dir)
292
+ temp_file = os.path.join(cwd, "temp")
293
+ if os.path.exists(temp_file):
294
+ shutil.rmtree(temp_file)
295
+
296
+ def check_args(self):
297
+ has_single_need_arg = self.bin or self.json or self.hpm or self.all
298
+ if not self.single:
299
+ if self.oem_path or self.uid or has_single_need_arg:
300
+ raise Exception("以下参数仅在单个CSR出包模式(-s,--single)下有效:[--oem, --hpm, -j, -b, -u, -a],请检查命令!")
301
+ elif not has_single_need_arg:
302
+ raise Exception("以下参数需至少携带一个:[--bin, --json, --hpm],可使用--all/-a指定索引选项。执行bingo build -h查看详细参数说明")
303
+ if not self.is_valid_json_path(self.max_size_map):
304
+ raise Exception(f"无效的JSON文件路径:{self.max_size_map}")
305
+
306
+ def get_sr_file_and_oem(self):
307
+ sr_make_options_list = []
308
+ csr_path = self.csr_path
309
+ oem_path = self.oem_path
310
+ oem_data = bytearray()
311
+ if not os.path.exists(csr_path):
312
+ raise FileNotFoundError(f"路径{csr_path}不存在")
313
+ if not os.path.isfile(csr_path):
314
+ raise Exception(f"{csr_path} 不是一个文件路径")
315
+ _, csr_ext = os.path.splitext(csr_path)
316
+ if not csr_ext == ".sr":
317
+ raise Exception(f"{csr_path} 不是一个有效的CSR文件")
318
+ log.info("开始执行单个CSR出包任务...")
319
+ log.info(f"执行出包的sr文件路径:{csr_path}")
320
+ if oem_path:
321
+ if not os.path.exists(oem_path):
322
+ raise FileNotFoundError(f"OEM文件路径{oem_path}不存在")
323
+ if not os.path.isfile(oem_path):
324
+ raise Exception(f"{oem_path} 不是一个文件路径")
325
+ _, oem_ext = os.path.splitext(oem_path)
326
+ if not oem_ext == ".bin":
327
+ raise Exception(f"OEM文件{oem_path}应为.bin文件")
328
+ with open(oem_path, 'rb') as f:
329
+ oem_data = bytearray(f.read())
330
+ name = os.path.basename(csr_path)
331
+ comp_name = os.path.splitext(name)[0]
332
+ with open(csr_path, 'r') as f:
333
+ sr_json = json.load(f)
334
+ sr_make_options_list.append(SrMakeOptions(comp_name, sr_json, oem_data))
335
+ return sr_make_options_list
336
+
337
+ def get_sr_files(self):
338
+ dir_path = Path(self.csr_path)
339
+ sr_files = [file for file in dir_path.glob("*.sr")]
340
+ sr_num = len(sr_files)
341
+ if sr_num == 1:
342
+ log.info("开始执行CSR出包任务...")
343
+ elif sr_num > 1:
344
+ log.info(f"开始执行CSR批量出包任务...共打包{sr_num}个文件")
345
+ sr_make_options_list = []
346
+ for sr_file in sr_files:
347
+ name = os.path.basename(sr_file)
348
+ log.info(f"执行出包的sr文件:{name}")
349
+ comp_name = os.path.splitext(name)[0]
350
+ with open(sr_file, 'r') as f:
351
+ sr_json = json.load(f)
352
+ oem_data = self.get_oem_data(dir_path, comp_name)
353
+ sr_make_options = SrMakeOptions(comp_name, sr_json, oem_data)
354
+ sr_make_options_list.append(sr_make_options)
355
+ return sr_make_options_list
356
+
357
+ def make_eeprom(self, hpm_temp_dir, sr_make_options_list):
358
+ flag = False
359
+ if os.path.exists(self.max_size_map):
360
+ with open(self.max_size_map, 'r') as f:
361
+ max_size_map = json.load(f)
362
+ else:
363
+ flag = True
364
+ log.info("设定eeprom大小限制为默认值(32kb)")
365
+ for options in sr_make_options_list:
366
+ if self.json or self.all:
367
+ log.info(f"生成{options.comp_name}.sr文件...")
368
+ sr_file = os.path.join(self.target_dir, f"{options.comp_name}.sr")
369
+ json_str = json.dumps(options.sr_json, ensure_ascii=False, indent=4)
370
+ with open(sr_file, 'w', encoding='utf-8') as f:
371
+ f.write(json_str)
372
+ if not self.do_build_eeprom():
373
+ continue
374
+ if flag:
375
+ max_eeprom_size = DEFAULT_EEPROM_SIZE_LIMIT
376
+ else:
377
+ max_eeprom_size = max_size_map.get(options.comp_name, DEFAULT_EEPROM_SIZE_LIMIT)
378
+ if not isinstance(max_eeprom_size, int) or max_eeprom_size <= 0:
379
+ raise Exception(f"{options.comp_name}sr文件的eeprom大小限制设定值{max_eeprom_size}错误,应为大于0的整数,单位(kb)")
380
+ self.make_sr_binary(options, hpm_temp_dir, max_eeprom_size)
381
+
382
+ def do_build_eeprom(self):
383
+ if not self.single or self.all:
384
+ return True
385
+ elif self.bin or self.hpm:
386
+ return True
387
+ else:
388
+ return False
389
+
390
+
391
+ class EepromBuild:
392
+ def __init__(self, bconfig, options, work_dir):
393
+ self.bconfig = bconfig
394
+ self.comp_name = options.comp_name
395
+ # devkit数据,json结构
396
+ self.dev_data = options.sr_json
397
+ # eeprom 规范版本号
398
+ self.format_version = self.get_sr_version(options.sr_json, "FormatVersion")
399
+ # 自描述数据固件版本
400
+ self.data_version = self.get_sr_version(options.sr_json, "DataVersion")
401
+ # 组件唯一标识数据
402
+ self.component_uid = options.uid
403
+ # OEM数据
404
+ self.oem_data = options.oem_data
405
+ # 工作目录
406
+ self.work_dir = work_dir
407
+ # eeprom头部长度,128 bytes
408
+ self.eeprom_header_len = 128
409
+ # 预留数据长度, 73 bytes
410
+ self.reserved_len = 73
411
+ # 组件UID数据长度,24 bytes
412
+ self.unique_id_len = 24
413
+ # 电子标签域数据长度 2048 bytes
414
+ self.elabel_len = 2048
415
+ # 系统信息域数据长度,1024 bytes
416
+ self.system_len = 1024
417
+ # 签名域数据长度,128 bytes
418
+ self.sign_len = 128
419
+ # psr头部数据长度,16 bytes
420
+ self.psr_header_len = 16
421
+ # csr头部数据长度,16 bytes
422
+ self.csr_header_len = 16
423
+ # 组件唯一标识数据
424
+ self.component_uid_data = bytearray()
425
+ # elabel及system区域数据预留,填充0x00,共3072字节
426
+ self.elabel_system_data = bytearray()
427
+ # 内部使用域数据预留,若无上传不做填充
428
+ self.internal_data = bytearray()
429
+ # 整机域数据
430
+ self.psr_data = bytearray()
431
+ # 组件域数据
432
+ self.csr_data = bytearray()
433
+ # 数字签名数据, 当前全0
434
+ self.sign_data = bytearray(self.sign_len)
435
+ # 自描述固件版本号数据,低字节在前高字节在后
436
+ self.des_ver_data = bytearray()
437
+ # 制化预留数据
438
+ self.des_reserve_data = bytearray()
439
+
440
+ @staticmethod
441
+ def get_sr_version(sr_json, key):
442
+ if key not in sr_json:
443
+ return ""
444
+ value = sr_json[key]
445
+ if isinstance(value, str):
446
+ return value
447
+ elif isinstance(value, float):
448
+ return format(value, ".2f")
449
+ return str(value)
450
+
451
+ @staticmethod
452
+ def resize_bytes_supplement(byte_arr: bytearray) -> bytearray:
453
+ '''将字节数组进行8位补齐'''
454
+ new_size = round_up_data_size(len(byte_arr))
455
+ if new_size == len(byte_arr):
456
+ return byte_arr
457
+ out_bytes = bytearray(new_size)
458
+ out_bytes[:len(byte_arr)] = byte_arr
459
+ return out_bytes
460
+
461
+ @staticmethod
462
+ def get_sha256_hash(data: bytearray) -> bytearray:
463
+ sha256 = hashlib.sha256()
464
+ sha256.update(data)
465
+ return bytearray(sha256.digest())
466
+
467
+ @staticmethod
468
+ def get_crc32_check_sum(data: bytearray):
469
+ crc32_value = binascii.crc32(data)
470
+ return crc32_value
471
+
472
+ @staticmethod
473
+ def zip_data(json_str) -> bytearray:
474
+ if not json_str:
475
+ return bytearray()
476
+ byte_data = json_str.encode("utf-8")
477
+ output_stream = io.BytesIO()
478
+ # 创建一个压缩流并写入到内存的BytesIO对象
479
+ with gzip.GzipFile(fileobj=output_stream, mode="wb") as f:
480
+ f.write(byte_data)
481
+ # 读取压缩后的字节流
482
+ compressed_data = output_stream.getvalue()
483
+ return compressed_data
484
+
485
+ def build_eeprom(self):
486
+ # 1. 从自描述数据中提取版本号信息
487
+ self.des_ver_data = self.build_description_version()
488
+ # 2. 从自描述数据中提取产品描述信息
489
+ self.des_reserve_data = self.build_description_reserve()
490
+ # 3. 从自描述数据中提取组件UID描述信息
491
+ self.component_uid_data = self.build_unique_id()
492
+ # 4. elabel和system定制化描述区域预留
493
+ self.elabel_system_data = self.build_elabel_system_data()
494
+ # 5. 创建内部使用区域数据
495
+ self.internal_data = self.build_internal_area()
496
+ # 6. 创建csr区域数据
497
+ self.csr_data = self.build_csr()
498
+ # 7. 创建eeprom header数据
499
+ eeprom_header_buf = self.build_eeprom_header()
500
+ # 8. 填充数据域
501
+ eeprom_buf_len = (
502
+ self.eeprom_header_len +
503
+ self.elabel_len +
504
+ self.system_len +
505
+ len(self.internal_data) +
506
+ len(self.psr_data) +
507
+ len(self.csr_data)
508
+ )
509
+ eeprom_buf = Buffer(eeprom_buf_len + self.sign_len)
510
+ eeprom_buf.put(eeprom_header_buf)
511
+ eeprom_buf.put(self.elabel_system_data)
512
+ eeprom_buf.put(self.internal_data)
513
+ eeprom_buf.put(self.psr_data)
514
+ eeprom_buf.put(self.csr_data)
515
+ eeprom_buf.put(self.sign_data)
516
+ log.info(f"{self.comp_name}: eeprom数据写入成功")
517
+ return eeprom_buf.array()
518
+
519
+ # 创建固件自定义描述版本号数据
520
+ def build_description_version(self):
521
+ ver_array = self.data_version.split(".")
522
+ out_bytes = bytearray(2)
523
+ if len(ver_array) != 2 or not all(part.isdigit() for part in ver_array):
524
+ return [0, 0]
525
+ out_bytes[0] = int(ver_array[1])
526
+ out_bytes[1] = int(ver_array[0])
527
+ return out_bytes
528
+
529
+ # 创建组件自定义描述数据
530
+ def build_description_reserve(self):
531
+ reserve_buf = Buffer(self.reserved_len)
532
+ return reserve_buf.array()
533
+
534
+ # 构建uniqueID
535
+ def build_unique_id(self):
536
+ unique_id_buf = Buffer(self.unique_id_len)
537
+ array_uid = bytearray(self.component_uid, "utf-8")
538
+ unique_id_buf.put(array_uid)
539
+ return unique_id_buf.array()
540
+
541
+ # 创建elabel域和system域占位数据
542
+ def build_elabel_system_data(self):
543
+ return bytearray(self.elabel_len + self.system_len)
544
+
545
+ # 根据 OEM 数据创建内部区域
546
+ def build_internal_area(self):
547
+ oem_data = self.oem_data
548
+ if len(oem_data) == 0:
549
+ return oem_data
550
+ rounded_size = round_up_data_size(len(oem_data))
551
+ buf = Buffer(rounded_size)
552
+ buf.put(oem_data)
553
+ return buf.array()
554
+
555
+ # 创建组件域描述数据
556
+ def build_csr(self):
557
+ csr_json_str = json.dumps(self.dev_data, separators=(",", ":"))
558
+ csr_bytes_arr = [bytearray(), bytearray(), bytearray(), bytearray()]
559
+ csr_body = self.build_csr_body(csr_json_str)
560
+ csr_bytes_arr[0] = csr_body
561
+ csr_header = self.build_csr_header(csr_bytes_arr)
562
+ csr_data = Buffer(round_up_data_size(len(csr_header) + len(csr_body)))
563
+ csr_data.put(csr_header)
564
+ csr_data.put(csr_body)
565
+ return csr_data.array()
566
+
567
+ def build_csr_body(self, csr_body_str: str):
568
+ # 1.处理CSR数据, 获取压缩后字节
569
+ zip_data = self.resize_bytes_supplement(self.zip_data(csr_body_str))
570
+ # 2. 计算CSR body数据域长度
571
+ body_size = len(zip_data) + 40
572
+ # 3. 创建CSR body字节缓冲区
573
+ csr_body_buf = Buffer(body_size)
574
+ # 4. 前32位校验码最后填充
575
+ csr_body_buf.set_position(32)
576
+ # 5. CSR数据格式码填充,1字节
577
+ csr_body_buf.put_uint8(JSON_DATA_FORMAT)
578
+ # 6. 数据压缩GZIP算法码填充,1字节
579
+ csr_body_buf.put_uint8(0x00)
580
+ # 7. 数据长度,2字节
581
+ csr_body_buf.put_uint16(len(zip_data) // 8)
582
+ # 8. 8字节对齐
583
+ csr_body_buf.set_position(csr_body_buf.position() + 4)
584
+ # 9. CSR压缩数据填充,字节数组
585
+ csr_body_buf.put(zip_data)
586
+ # 10, CSR完整性校验
587
+ csr_body_buf.set_position(0)
588
+ csr_body_buf.put(self.get_sha256_hash(csr_body_buf.array()))
589
+ return csr_body_buf.array()
590
+
591
+ def build_csr_header(self, csr_bytes_arr: list) -> bytearray:
592
+ csr_header = CsrHeader(self.csr_header_len, csr_bytes_arr)
593
+ # 1. 初始化csr header buffer
594
+ csr_header_buf = Buffer(self.csr_header_len)
595
+ # 2. csr域格式版本, 1字节
596
+ csr_header_buf.put_uint8(csr_header.csr_ver)
597
+ # 3. CSR域数量,1字节
598
+ csr_header_buf.put_uint8(csr_header.csr_count)
599
+ # 4. csr子域偏移量,8字节
600
+ csr_header_buf.put(csr_header.csr_offset.array())
601
+ # 5. 占位,填充0x00,2字节
602
+ csr_header_buf.put_uint16(csr_header.padding)
603
+ # 6. csr header校验,4字节
604
+ csr_header_buf.put_uint32(self.get_crc32_check_sum(csr_header_buf.array()))
605
+ return csr_header_buf.array()
606
+
607
+ def build_eeprom_header(self):
608
+ eeprom_header_buf = Buffer(self.eeprom_header_len)
609
+ e_header = EepromHeader(len(self.psr_data), len(self.csr_data), len(self.internal_data))
610
+ # 1. 12位天池规范校验码 12字节
611
+ eeprom_header_buf.put(e_header.code)
612
+ # 2. 规范版本号 1字节
613
+ eeprom_header_buf.put_uint8(e_header.header_ver)
614
+ # 3. 电子组标签域偏移,0x00填充 2字节 16
615
+ eeprom_header_buf.put_uint16(e_header.elabel_off)
616
+ # 4. 系统定制化描述信息(System Description Address) 偏移,0x00填充,2字节
617
+ eeprom_header_buf.put_uint16(e_header.system_off) # 272
618
+ # 5,内部适用域(Internal Use Area Address)偏移,0x00填充,2字节
619
+ eeprom_header_buf.put_uint16(e_header.internal_area_off)
620
+ # 6. 整机描述域偏移,2字节
621
+ eeprom_header_buf.put_uint16(e_header.psr_off)
622
+ # 7. 组件描述域偏移,2字节
623
+ eeprom_header_buf.put_uint16(e_header.csr_off)
624
+ # 8. 数据签名区域偏移,2字节
625
+ eeprom_header_buf.put_uint16(e_header.sign_off)
626
+ # 9. 定制化预留数据填充0x00,73字节
627
+ eeprom_header_buf.put(self.des_reserve_data)
628
+ # 10. 自描述固件版本号数据,低字节在前高字节在后,2字节
629
+ eeprom_header_buf.put(self.des_ver_data)
630
+ # 11. 组件唯一标识,24字节
631
+ eeprom_header_buf.put(self.component_uid_data)
632
+ # 12. CRC32 校验和(4字节)
633
+ eeprom_header_buf.put_uint32(self.get_crc32_check_sum(eeprom_header_buf.array()))
634
+ return eeprom_header_buf.array()
635
+
636
+
637
+ class EepromHeader:
638
+ def __init__(self, psr_size, csr_size, internal_size):
639
+ self.code = bytearray([0, 0, 0, 0, 0, 0, 0, 0, 90, 165, 90, 165])
640
+ self.header_ver = 0x03
641
+ self.elabel_off = 16
642
+ self.system_off = 272
643
+ self.internal_area_off = 0x0000
644
+ pre_area_off = 400
645
+ if internal_size == 0:
646
+ self.internal_area_off = 0x0000
647
+ else:
648
+ self.internal_area_off = pre_area_off
649
+ if psr_size == 0:
650
+ self.psr_off = 0x0000
651
+ else:
652
+ self.psr_off = pre_area_off + (internal_size // 8)
653
+ if csr_size == 0:
654
+ self.csr_off = 0x0000
655
+ else:
656
+ self.csr_off = pre_area_off + ((internal_size + psr_size) // 8)
657
+ self.sign_off = pre_area_off + ((internal_size + psr_size + csr_size) // 8)
658
+
659
+
660
+ class HpmBuild:
661
+ # Description: hpm打包初始化函数
662
+ def __init__(self, bconfig, dest_file, work_dir):
663
+ self.bconfig = bconfig
664
+ # hpm包文件名
665
+ self.hpm_name = "devkit.hpm"
666
+ # 打包后结果文件存放路径
667
+ self.dest_path = dest_file
668
+ # 打包目录
669
+ self.hpm_temp_dir = os.path.join(work_dir, "hpm_temp")
670
+ # 打包路径下配置文件,存放在目录csr_packet下
671
+ self.package_list = [
672
+ "afteraction.sh", "beforeaction.sh", "CfgFileList.conf",
673
+ "hpm_devkit.config", "image.filelist", "packet.sh",
674
+ "update.cfg"
675
+ ]
676
+ if os.path.exists(HPM_PACK_PATH):
677
+ shutil.copytree(HPM_PACK_PATH, self.hpm_temp_dir, dirs_exist_ok=True)
678
+ # 打包后得到的hpm包
679
+ self.hpm_file = os.path.join(self.hpm_temp_dir, self.hpm_name)
680
+
681
+ # hpm包制作工具检查
682
+ @staticmethod
683
+ def check_hpm_tools():
684
+ log.info("开始hpm包制作工具检查...")
685
+ ret = tool.run_command("which hpmimage filesizecheck")
686
+ if ret is None or ret.returncode != 0:
687
+ raise Exception("hpm 包制作工具缺失,请检查bingo是否正确安装")
688
+
689
+ # 打包路径下配置文件校验
690
+ def check_dir(self):
691
+ for config_file in self.package_list:
692
+ if not os.path.exists(os.path.join(self.hpm_temp_dir, config_file)):
693
+ raise Exception(f"Failed to find hpm package config file: {config_file}")
694
+
695
+ # 执行脚本构建hpm
696
+ def packet_hpm(self):
697
+ log.info("开始执行构建脚本生成hpm包...")
698
+ packet_script = os.path.join(self.hpm_temp_dir, "packet.sh")
699
+ os.chdir(self.hpm_temp_dir)
700
+ ret = tool.run_command(f"bash {packet_script} package {self.hpm_temp_dir}", command_echo=False)
701
+ if ret.returncode != 0:
702
+ raise Exception(f"Failed to pack the hpm, error msg: {ret}")
703
+ elif not os.path.exists(self.hpm_file):
704
+ raise Exception("Failed to pack the hpm.")
705
+ os.chdir(self.hpm_temp_dir)
706
+ ret = tool.run_command(f"bash {self.hpm_temp_dir}/packet.sh rebuild {self.hpm_temp_dir}", command_echo=False)
707
+ if ret.returncode != 0 or not os.path.exists(self.hpm_file):
708
+ raise Exception(f"构造hpm包失败:{ret.stderr}.")
709
+ shutil.move(self.hpm_file, self.dest_path)
710
+
711
+ def run(self):
712
+ self.check_dir()
713
+ self.check_hpm_tools()
714
+ self.packet_hpm()
715
+
716
+
717
+ # 文件名生成时间戳
718
+ def get_timestamp():
719
+ now = datetime.now(tz=timezone(timedelta(hours=8)))
720
+ return now.strftime("%Y%m%d%H%M%S")
721
+
722
+
723
+ def round_up_data_size(data_size: int) -> int:
724
+ return ((data_size + 7) // 8) * 8