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.
- bmcgo/__init__.py +12 -0
- bmcgo/bmcgo.py +22 -0
- bmcgo/bmcgo_config.py +176 -0
- bmcgo/cli/__init__.py +10 -0
- bmcgo/cli/cli.py +584 -0
- bmcgo/codegen/__init__.py +14 -0
- bmcgo/codegen/c/__init__.py +9 -0
- bmcgo/codegen/c/annotation.py +52 -0
- bmcgo/codegen/c/argument.py +42 -0
- bmcgo/codegen/c/codegen.py +153 -0
- bmcgo/codegen/c/comment.py +22 -0
- bmcgo/codegen/c/ctype_defination.py +353 -0
- bmcgo/codegen/c/helper.py +87 -0
- bmcgo/codegen/c/interface.py +63 -0
- bmcgo/codegen/c/method.py +82 -0
- bmcgo/codegen/c/property.py +180 -0
- bmcgo/codegen/c/renderer.py +21 -0
- bmcgo/codegen/c/signal.py +64 -0
- bmcgo/codegen/c/template/client.c.mako +145 -0
- bmcgo/codegen/c/template/client.h.mako +36 -0
- bmcgo/codegen/c/template/interface.c.mako +0 -0
- bmcgo/codegen/c/template/interface.introspect.xml.mako +99 -0
- bmcgo/codegen/c/template/micro_component.c.mako +32 -0
- bmcgo/codegen/c/template/public.c.mako +228 -0
- bmcgo/codegen/c/template/public.h.mako +128 -0
- bmcgo/codegen/c/template/server.c.mako +104 -0
- bmcgo/codegen/c/template/server.h.mako +36 -0
- bmcgo/codegen/lua/.lua-format +7 -0
- bmcgo/codegen/lua/Makefile +101 -0
- bmcgo/codegen/lua/__init__.py +9 -0
- bmcgo/codegen/lua/codegen.py +171 -0
- bmcgo/codegen/lua/proto/Makefile +87 -0
- bmcgo/codegen/lua/proto/ipmi_types.proto +17 -0
- bmcgo/codegen/lua/proto/types.proto +52 -0
- bmcgo/codegen/lua/script/check_intfs.py +161 -0
- bmcgo/codegen/lua/script/dto/__init__.py +11 -0
- bmcgo/codegen/lua/script/dto/exception.py +53 -0
- bmcgo/codegen/lua/script/dto/kepler_abstract.py +47 -0
- bmcgo/codegen/lua/script/dto/options.py +33 -0
- bmcgo/codegen/lua/script/dto/print_simple.py +19 -0
- bmcgo/codegen/lua/script/dto/redfish_api.py +241 -0
- bmcgo/codegen/lua/script/dto/url_route.py +195 -0
- bmcgo/codegen/lua/script/gen_db_json.py +444 -0
- bmcgo/codegen/lua/script/gen_depends.py +89 -0
- bmcgo/codegen/lua/script/gen_entry.py +263 -0
- bmcgo/codegen/lua/script/gen_feature_json.py +156 -0
- bmcgo/codegen/lua/script/gen_historical_local_db_json.py +88 -0
- bmcgo/codegen/lua/script/gen_intf_json.py +261 -0
- bmcgo/codegen/lua/script/gen_intf_rpc_json.py +575 -0
- bmcgo/codegen/lua/script/gen_ipmi_json.py +485 -0
- bmcgo/codegen/lua/script/gen_mdb_json.py +117 -0
- bmcgo/codegen/lua/script/gen_rpc_msg_json.py +487 -0
- bmcgo/codegen/lua/script/gen_schema.py +302 -0
- bmcgo/codegen/lua/script/ipmi_types_pb2.py +135 -0
- bmcgo/codegen/lua/script/loader/__init__.py +11 -0
- bmcgo/codegen/lua/script/loader/file_utils.py +33 -0
- bmcgo/codegen/lua/script/loader/kepler_abstract_collect.py +79 -0
- bmcgo/codegen/lua/script/loader/kepler_abstract_loader.py +47 -0
- bmcgo/codegen/lua/script/loader/redfish_loader.py +127 -0
- bmcgo/codegen/lua/script/lua_format.py +62 -0
- bmcgo/codegen/lua/script/mds_util.py +385 -0
- bmcgo/codegen/lua/script/merge_model.py +330 -0
- bmcgo/codegen/lua/script/merge_proto_algo.py +85 -0
- bmcgo/codegen/lua/script/proto_loader.py +47 -0
- bmcgo/codegen/lua/script/proto_plugin.py +140 -0
- bmcgo/codegen/lua/script/redfish_source_tree.py +118 -0
- bmcgo/codegen/lua/script/render_utils/__init__.py +38 -0
- bmcgo/codegen/lua/script/render_utils/base.py +25 -0
- bmcgo/codegen/lua/script/render_utils/client_lua.py +98 -0
- bmcgo/codegen/lua/script/render_utils/controller_lua.py +71 -0
- bmcgo/codegen/lua/script/render_utils/db_lua.py +224 -0
- bmcgo/codegen/lua/script/render_utils/error_lua.py +185 -0
- bmcgo/codegen/lua/script/render_utils/factory.py +52 -0
- bmcgo/codegen/lua/script/render_utils/ipmi_lua.py +159 -0
- bmcgo/codegen/lua/script/render_utils/ipmi_message_lua.py +24 -0
- bmcgo/codegen/lua/script/render_utils/mdb_lua.py +177 -0
- bmcgo/codegen/lua/script/render_utils/mdb_register.py +215 -0
- bmcgo/codegen/lua/script/render_utils/message_lua.py +26 -0
- bmcgo/codegen/lua/script/render_utils/messages_lua.py +156 -0
- bmcgo/codegen/lua/script/render_utils/model_lua.py +485 -0
- bmcgo/codegen/lua/script/render_utils/old_model_lua.py +429 -0
- bmcgo/codegen/lua/script/render_utils/plugin_lua.py +38 -0
- bmcgo/codegen/lua/script/render_utils/redfish_proto.py +86 -0
- bmcgo/codegen/lua/script/render_utils/request_lua.py +76 -0
- bmcgo/codegen/lua/script/render_utils/service_lua.py +130 -0
- bmcgo/codegen/lua/script/render_utils/utils_message_lua.py +125 -0
- bmcgo/codegen/lua/script/render_utils/validate_lua.py +221 -0
- bmcgo/codegen/lua/script/sep_ipmi_message_cmds.py +217 -0
- bmcgo/codegen/lua/script/template.py +166 -0
- bmcgo/codegen/lua/script/types_pb2.py +516 -0
- bmcgo/codegen/lua/script/utils.py +663 -0
- bmcgo/codegen/lua/script/validate.py +80 -0
- bmcgo/codegen/lua/script/yaml_to_json.py +73 -0
- bmcgo/codegen/lua/templates/Makefile +114 -0
- bmcgo/codegen/lua/templates/apps/Makefile +261 -0
- bmcgo/codegen/lua/templates/apps/Makefile.mdb.mk +64 -0
- bmcgo/codegen/lua/templates/apps/app.lua.mako +19 -0
- bmcgo/codegen/lua/templates/apps/class.lua.mako +35 -0
- bmcgo/codegen/lua/templates/apps/client.lua.mako +429 -0
- bmcgo/codegen/lua/templates/apps/controller.lua.mako +276 -0
- bmcgo/codegen/lua/templates/apps/datas.lua.mako +8 -0
- bmcgo/codegen/lua/templates/apps/db.lua.mako +89 -0
- bmcgo/codegen/lua/templates/apps/entry.lua.mako +128 -0
- bmcgo/codegen/lua/templates/apps/feature.lua.mako +37 -0
- bmcgo/codegen/lua/templates/apps/generate_route.mako +25 -0
- bmcgo/codegen/lua/templates/apps/impl_feature.lua.mako +72 -0
- bmcgo/codegen/lua/templates/apps/ipmi.lua.mako +97 -0
- bmcgo/codegen/lua/templates/apps/ipmi_cmd.lua.mako +18 -0
- bmcgo/codegen/lua/templates/apps/ipmi_message.lua.mako +36 -0
- bmcgo/codegen/lua/templates/apps/local_db.lua.mako +263 -0
- bmcgo/codegen/lua/templates/apps/main.lua.mako +25 -0
- bmcgo/codegen/lua/templates/apps/mc.lua.mako +77 -0
- bmcgo/codegen/lua/templates/apps/mdb.lua.mako +45 -0
- bmcgo/codegen/lua/templates/apps/mdb_interface.lua.mako +73 -0
- bmcgo/codegen/lua/templates/apps/message.lua.mako +38 -0
- bmcgo/codegen/lua/templates/apps/model.lua.mako +239 -0
- bmcgo/codegen/lua/templates/apps/orm_classes.lua.mako +16 -0
- bmcgo/codegen/lua/templates/apps/plugin.lua.mako +8 -0
- bmcgo/codegen/lua/templates/apps/redfish.proto.mako +47 -0
- bmcgo/codegen/lua/templates/apps/service.lua.mako +440 -0
- bmcgo/codegen/lua/templates/apps/signal_listen.lua.mako +19 -0
- bmcgo/codegen/lua/templates/apps/utils/default_intf.lua.mako +41 -0
- bmcgo/codegen/lua/templates/apps/utils/enum.mako +10 -0
- bmcgo/codegen/lua/templates/apps/utils/imports.mako +13 -0
- bmcgo/codegen/lua/templates/apps/utils/mdb_intf.lua.mako +25 -0
- bmcgo/codegen/lua/templates/apps/utils/mdb_obj.lua.mako +23 -0
- bmcgo/codegen/lua/templates/apps/utils/message.mako +160 -0
- bmcgo/codegen/lua/templates/apps/utils/request.lua.mako +59 -0
- bmcgo/codegen/lua/templates/apps/utils/validate.mako +83 -0
- bmcgo/codegen/lua/templates/errors.lua.mako +36 -0
- bmcgo/codegen/lua/templates/messages.lua.mako +32 -0
- bmcgo/codegen/lua/templates/new_app/.clang-format.mako +170 -0
- bmcgo/codegen/lua/templates/new_app/.gitignore.mako +26 -0
- bmcgo/codegen/lua/templates/new_app/CHANGELOG.md.mako +0 -0
- bmcgo/codegen/lua/templates/new_app/CMakeLists.txt.mako +29 -0
- bmcgo/codegen/lua/templates/new_app/Makefile.mako +25 -0
- bmcgo/codegen/lua/templates/new_app/README.md.mako +0 -0
- bmcgo/codegen/lua/templates/new_app/conanfile.py.mako +7 -0
- bmcgo/codegen/lua/templates/new_app/config.cfg.mako +6 -0
- bmcgo/codegen/lua/templates/new_app/mds/model.json.mako +3 -0
- bmcgo/codegen/lua/templates/new_app/mds/service.json.mako +21 -0
- bmcgo/codegen/lua/templates/new_app/permissions.ini.mako +16 -0
- bmcgo/codegen/lua/templates/new_app/src/lualib/${project_name}_app.lua.mako +16 -0
- bmcgo/codegen/lua/templates/new_app/src/service/main.lua.mako +25 -0
- bmcgo/codegen/lua/templates/new_app/test/integration/test_${project_name}.conf.mako +9 -0
- bmcgo/codegen/lua/templates/new_app/test/integration/test_${project_name}.lua.mako +47 -0
- bmcgo/codegen/lua/templates/new_app/test/unit/test.lua.mako +23 -0
- bmcgo/codegen/lua/templates/new_app/user_conf/rootfs/etc/systemd/system/${project_name}.service.mako +18 -0
- bmcgo/codegen/lua/templates/new_app/user_conf/rootfs/etc/systemd/system/multi-user.target.wants/${project_name}.service.link +1 -0
- bmcgo/component/__init__.py +10 -0
- bmcgo/component/analysis/analysis.py +183 -0
- bmcgo/component/analysis/build_deps.py +165 -0
- bmcgo/component/analysis/data_deps.py +333 -0
- bmcgo/component/analysis/dep-rules.json +912 -0
- bmcgo/component/analysis/dep_node.py +110 -0
- bmcgo/component/analysis/intf_deps.py +163 -0
- bmcgo/component/analysis/intf_validation.py +254 -0
- bmcgo/component/analysis/rule.py +211 -0
- bmcgo/component/analysis/smc_dfx_whitelist.json +11 -0
- bmcgo/component/analysis/sr_validation.py +391 -0
- bmcgo/component/build.py +222 -0
- bmcgo/component/component_dt_version_parse.py +348 -0
- bmcgo/component/component_helper.py +114 -0
- bmcgo/component/coverage/__init__.py +11 -0
- bmcgo/component/coverage/c_incremental_cov_report.template +53 -0
- bmcgo/component/coverage/incremental_cov.py +464 -0
- bmcgo/component/deploy.py +110 -0
- bmcgo/component/gen.py +169 -0
- bmcgo/component/package_info.py +236 -0
- bmcgo/component/template/conanbase.py.mako +278 -0
- bmcgo/component/template/conanfile.deploy.py.mako +40 -0
- bmcgo/component/test.py +947 -0
- bmcgo/errors.py +119 -0
- bmcgo/frame.py +217 -0
- bmcgo/functional/__init__.py +10 -0
- bmcgo/functional/analysis.py +96 -0
- bmcgo/functional/bmc_studio_action.py +98 -0
- bmcgo/functional/check.py +185 -0
- bmcgo/functional/conan_index_build.py +251 -0
- bmcgo/functional/config.py +332 -0
- bmcgo/functional/csr_build.py +724 -0
- bmcgo/functional/deploy.py +263 -0
- bmcgo/functional/diff.py +235 -0
- bmcgo/functional/fetch.py +235 -0
- bmcgo/functional/full_component.py +391 -0
- bmcgo/functional/maintain.py +381 -0
- bmcgo/functional/new.py +166 -0
- bmcgo/functional/schema_valid.py +111 -0
- bmcgo/functional/simple_sign.py +104 -0
- bmcgo/functional/upgrade.py +78 -0
- bmcgo/ipmigen/__init__.py +13 -0
- bmcgo/ipmigen/ctype_defination.py +82 -0
- bmcgo/ipmigen/ipmigen.py +309 -0
- bmcgo/ipmigen/template/cmd.c.mako +366 -0
- bmcgo/ipmigen/template/ipmi.c.mako +25 -0
- bmcgo/ipmigen/template/ipmi.h.mako +51 -0
- bmcgo/logger.py +176 -0
- bmcgo/misc.py +117 -0
- bmcgo/target/app.yml +17 -0
- bmcgo/target/install_sdk.yml +15 -0
- bmcgo/target/personal.yml +53 -0
- bmcgo/target/publish.yml +45 -0
- bmcgo/tasks/__init__.py +11 -0
- bmcgo/tasks/download_buildtools_hm.py +124 -0
- bmcgo/tasks/misc.py +15 -0
- bmcgo/tasks/task.py +354 -0
- bmcgo/tasks/task_build_conan.py +714 -0
- bmcgo/tasks/task_build_rootfs_img.py +595 -0
- bmcgo/tasks/task_buildgppbin.py +88 -0
- bmcgo/tasks/task_buildhpm_ext4.py +82 -0
- bmcgo/tasks/task_create_interface_config.py +122 -0
- bmcgo/tasks/task_download_buildtools.py +99 -0
- bmcgo/tasks/task_download_dependency.py +72 -0
- bmcgo/tasks/task_hpm_envir_prepare.py +112 -0
- bmcgo/tasks/task_packet_to_supporte.py +87 -0
- bmcgo/tasks/task_prepare.py +105 -0
- bmcgo/tasks/task_sign_and_pack_hpm.py +42 -0
- bmcgo/utils/__init__.py +10 -0
- bmcgo/utils/buffer.py +128 -0
- bmcgo/utils/combine_json_schemas.py +170 -0
- bmcgo/utils/component_post.py +54 -0
- bmcgo/utils/component_version_check.py +86 -0
- bmcgo/utils/config.py +1067 -0
- bmcgo/utils/fetch_component_code.py +232 -0
- bmcgo/utils/install_manager.py +61 -0
- bmcgo/utils/installations/__init__.py +10 -0
- bmcgo/utils/installations/base_installer.py +70 -0
- bmcgo/utils/installations/install_consts.py +30 -0
- bmcgo/utils/installations/install_plans/bingo.yml +11 -0
- bmcgo/utils/installations/install_workflow.py +50 -0
- bmcgo/utils/installations/installers/apt_installer.py +177 -0
- bmcgo/utils/installations/installers/pip_installer.py +46 -0
- bmcgo/utils/installations/version_util.py +100 -0
- bmcgo/utils/mapping_config_patch.py +443 -0
- bmcgo/utils/perf_analysis.py +114 -0
- bmcgo/utils/tools.py +704 -0
- bmcgo/worker.py +417 -0
- openubmc_bingo-0.5.240.dist-info/METADATA +30 -0
- openubmc_bingo-0.5.240.dist-info/RECORD +242 -0
- openubmc_bingo-0.5.240.dist-info/WHEEL +5 -0
- openubmc_bingo-0.5.240.dist-info/entry_points.txt +2 -0
- 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
|