From 9013f1bbeac4464298e48bf6e5d7cbd89c86e192 Mon Sep 17 00:00:00 2001 From: Qiumiao Zhang Date: Fri, 12 Jan 2024 02:30:01 +0000 Subject: [PATCH] add TPCM support with ipmi channel Signed-off-by: Qiumiao Zhang (cherry picked from commit d079ce35df750d00d59fc4150fc11b7db4be6a45) --- add-TPCM-support-with-ipmi-channel.patch | 772 ++++++++++++++++++ grub.macros | 2 +- grub.patches | 2 + grub2.spec | 10 +- ...rification-when-not-loading-grub.cfg.patch | 29 + 5 files changed, 813 insertions(+), 2 deletions(-) create mode 100644 add-TPCM-support-with-ipmi-channel.patch create mode 100644 skip-verification-when-not-loading-grub.cfg.patch diff --git a/add-TPCM-support-with-ipmi-channel.patch b/add-TPCM-support-with-ipmi-channel.patch new file mode 100644 index 0000000..fe0168c --- /dev/null +++ b/add-TPCM-support-with-ipmi-channel.patch @@ -0,0 +1,772 @@ +From 2d7ef4b34427e1e1b2f55fdcc7868e7ce001a194 Mon Sep 17 00:00:00 2001 +From: "t.feng" +Date: Tue, 28 Feb 2023 16:25:30 +0800 +Subject: [PATCH] add tpcm support with ipmi channel + +t.feng(2): +add tpcm support with ipmi channel +use uefi hash interface + +zhangqiumiao(3): +reset response length when getting results failed +fix firmwarehash length and uiCmdLength error +clean code + +zhangqiumiao(4): +support control switch +modify GRUB_IPMI_TIMEOUT_MS from 7000 to 2000 + +Signed-off-by: "t.feng" +Signed-off-by: zhangqiumiao +--- + grub-core/Makefile.core.def | 6 + + grub-core/commands/efi/tpcm.c | 476 ++++++++++++++++++++++++++++++++++ + include/grub/efi/tpcm.h | 236 +++++++++++++++++ + 3 files changed, 718 insertions(+) + create mode 100644 grub-core/commands/efi/tpcm.c + create mode 100644 include/grub/efi/tpcm.h + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 6b00eb5..ee6ff17 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -2564,6 +2564,12 @@ module = { + enable = efi; + }; + ++module = { ++ name = tpcm_kunpeng; ++ common = commands/efi/tpcm.c; ++ enable = efi; ++}; ++ + module = { + name = tr; + common = commands/tr.c; +diff --git a/grub-core/commands/efi/tpcm.c b/grub-core/commands/efi/tpcm.c +new file mode 100644 +index 0000000..57a4cea +--- /dev/null ++++ b/grub-core/commands/efi/tpcm.c +@@ -0,0 +1,476 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++#define TRANS(value) (((value << 24 ) & 0xFF000000) | \ ++ ((value << 8 ) & 0x00FF0000) | \ ++ ((value >> 8 ) & 0x0000FF00) | \ ++ ((value >> 24 ) & 0x000000FF)) ++ ++static grub_efi_guid_t gIpmiInterfaceProtocolGuid = EFI_TPCM_GUID; ++static grub_efi_guid_t hash2_service_binding_guid = GRUB_EFI_HASH2_SERVICE_BINDING_PROTOCOL_GUID; ++static grub_efi_guid_t hash2_guid = GRUB_EFI_HASH2_PROTOCOL_GUID; ++static grub_efi_guid_t sm3_guid = GRUB_HASH_ALGORITHM_SM3_GUID; ++ ++static grub_efi_ipmi_interface_protocol_t *tpcm_ipmi; ++static grub_efi_uint16_t grub_tcpm_file_type = GRUB_FILE_TYPE_NONE; ++ ++static grub_uint32_t bm_stage_base = 2000; ++static grub_efi_uint8_t permissive = 0; ++ ++static grub_efi_handle_t ++grub_efi_service_binding (grub_efi_guid_t *service_binding_guid) ++{ ++ grub_efi_service_binding_t *service; ++ grub_efi_status_t status; ++ grub_efi_handle_t child_dev = NULL; ++ grub_efi_handle_t *handles; ++ grub_efi_uintn_t num_handles; ++ ++ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, service_binding_guid, 0, &num_handles); ++ if (!handles) ++ { ++ grub_printf ("couldn't locate service binding protocol handles\n"); ++ return NULL; ++ } ++ ++ service = grub_efi_open_protocol (handles[0], service_binding_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ if (!service) ++ { ++ grub_printf ("couldn't open efi service binding protocol\n"); ++ return NULL; ++ } ++ ++ status = efi_call_2 (service->create_child, service, &child_dev); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_printf ("Failed to create child device of efi service %x\n", status); ++ return NULL; ++ } ++ ++ return child_dev; ++} ++ ++static inline void ++util_dump_hex (const char *name, void *p, int bytes) ++{ ++ ++ int i = 0; ++ char *data = p; ++ int add_newline = 1; ++ grub_dprintf ("tpcm", "%s length=%d:\n", name, bytes); ++ if (bytes != 0) ++ { ++ grub_dprintf ("tpcm", "%02x ", (unsigned char)data[i]); ++ i++; ++ } ++ while (i < bytes) ++ { ++ grub_dprintf ("tpcm", "%02x ", (unsigned char)data[i]); ++ i++; ++ if (i % 16 == 0) ++ { ++ grub_dprintf("tpcm", "\n"); ++ add_newline = 0; ++ } ++ else ++ add_newline = 1; ++ } ++ if (add_newline) ++ grub_dprintf("tpcm", "\n"); ++} ++ ++static grub_efi_status_t ++grub_efi_hash (unsigned char *buf, grub_size_t size, unsigned char *content) ++{ ++ grub_efi_status_t status = GRUB_EFI_SUCCESS; ++ grub_efi_hash2_protocol_t *hash2; ++ grub_efi_handle_t hash_handle; ++ unsigned char output[DEFAULT_HASH_SIZE] = {0}; ++ grub_dprintf("tpcm", "grub_efi_hash binding service.\n"); ++ hash_handle = grub_efi_service_binding (&hash2_service_binding_guid); ++ if (!hash_handle) ++ { ++ grub_dprintf ("tpcm", "hash2 service binding failed.\n"); ++ status = GRUB_EFI_NOT_FOUND; ++ goto fail; ++ } ++ grub_dprintf("tpcm", "grub_efi_hash binding service success.\n"); ++ hash2 = grub_efi_open_protocol (hash_handle, &hash2_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ if (!hash2) ++ { ++ grub_dprintf ("tpcm", "hash2 protocol open failed.\n"); ++ status = GRUB_EFI_PROTOCOL_ERROR; ++ goto fail; ++ } ++ grub_dprintf("tpcm", "grub_efi_hash get protocol success.\n"); ++ status = hash2->hash_init(hash2, &sm3_guid); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_dprintf("tpcm", "hash_init failed.\n"); ++ goto fail; ++ } ++ status = hash2->hash_update(hash2, buf, size); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_dprintf("tpcm", "hash_update failed.\n"); ++ goto fail; ++ } ++ status = hash2->hash_final(hash2, output); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_dprintf("tpcm", "hash_final failed.\n"); ++ goto fail; ++ } ++ util_dump_hex ("tpcm BIOS hash output: ", output, DEFAULT_HASH_SIZE); ++ grub_memcpy(content, output, DEFAULT_HASH_SIZE); ++ ++fail: ++ return status; ++} ++ ++static grub_err_t ++tpcm_ipmi_init (grub_file_t io, ++ enum grub_file_type type __attribute__ ((unused)), ++ void **context, enum grub_verify_flags *flags) ++{ ++ *context = io->name; ++ grub_tcpm_file_type = type & GRUB_FILE_TYPE_MASK; ++ *flags |= GRUB_VERIFY_FLAGS_SINGLE_CHUNK; ++ return GRUB_ERR_NONE; ++} ++ ++static grub_efi_uint8_t ++get_firmware_hash_content(unsigned char *buf, grub_size_t size, unsigned char *content) ++{ ++ grub_efi_status_t status; ++ ++ grub_dprintf ("tpcm", "grub_efi_hash:\n"); ++ status = grub_efi_hash (buf, size, content); ++ ++ return status; ++} ++ ++static grub_err_t ++grub_tpcm_set_firmware_detailtype (grub_efi_uint8_t *type) ++{ ++ switch (grub_tcpm_file_type) ++ { ++ case GRUB_FILE_TYPE_LINUX_KERNEL: ++ *type = IPMI_FW_DETAIL_KERNEL; ++ break; ++ case GRUB_FILE_TYPE_LINUX_INITRD: ++ *type = IPMI_FW_DETAIL_INITRD; ++ break; ++ case GRUB_FILE_TYPE_CONFIG: ++ *type = IPMI_FW_DETAIL_GRUB_CFG; ++ break; ++ default: ++ grub_dprintf ("tpcm", "%d is not a file type that TPCM cares about.\n", grub_tcpm_file_type); ++ grub_tcpm_file_type = GRUB_FILE_TYPE_NONE; ++ break; ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++static void ++grub_tpcm_fillup_content (OEM_BMC_MEASURE_REQUSET *request_data, unsigned char *output) ++{ ++ grub_efi_uint32_t filename_len = 0; ++ switch (grub_tcpm_file_type) ++ { ++ case GRUB_FILE_TYPE_LINUX_KERNEL: ++ filename_len = grub_strlen("kernel"); ++ grub_memcpy ((grub_efi_uint8_t *)(request_data->FirmwareHashContent.uaObj), ++ "kernel", filename_len); ++ break; ++ case GRUB_FILE_TYPE_LINUX_INITRD: ++ filename_len = grub_strlen("initrd"); ++ grub_memcpy ((grub_efi_uint8_t *)(request_data->FirmwareHashContent.uaObj), ++ "initrd", filename_len); ++ break; ++ case GRUB_FILE_TYPE_CONFIG: ++ filename_len = grub_strlen("grub.cfg"); ++ grub_memcpy ((grub_efi_uint8_t *)(request_data->FirmwareHashContent.uaObj), ++ "grub.cfg", filename_len); ++ break; ++ default: ++ grub_dprintf ("tpcm", "%d is not a file type that TPCM cares about.\n", grub_tcpm_file_type); ++ break; ++ } ++ ++ request_data->FirmwareHashContent.uiCmdTag = TRANS (TPCM_TAG_REQ_COMMAND); ++ request_data->FirmwareHashContent.uiCmdLength = TRANS (sizeof (extern_simple_bmeasure_req_st)); ++ request_data->FirmwareHashContent.uiCmdCode = TRANS (TPCM_ORD_ExternSimpleBootMeasure); ++ request_data->FirmwareHashContent.uiPcr = TRANS (0); ++ ++ grub_uint32_t stage_base = bm_stage_base++; ++ request_data->FirmwareHashContent.uiStage = TRANS (stage_base); ++ ++ grub_memcpy ((grub_efi_uint8_t *)(request_data->FirmwareHashContent.uaDigest), ++ output, DEFAULT_HASH_SIZE); ++ request_data->FirmwareHashContent.uiObjLen = TRANS (filename_len); ++ ++ return; ++} ++ ++static grub_efi_status_t ++grub_tpcm_request_result (void) ++{ ++ grub_efi_status_t status = GRUB_EFI_SUCCESS; ++ grub_ipmi_cmd_header request = {IPMI_BMC_LUN, ++ IPMI_NETFN_OEM, ++ IPMI_CMD_GET_MEASURE_PARM}; ++ grub_efi_uint8_t response_length; ++ OEM_BMC_GET_RESULT_REQUSET get_result_request_data; ++ OEM_BMC_GET_RESULT_RESPONSE get_result_response_data; ++ ++ grub_efi_int16_t timeout_ms = GRUB_IPMI_TIMEOUT_MS; ++ ++ grub_memset (&get_result_request_data, 0, sizeof(get_result_request_data)); ++ grub_memset (&get_result_response_data, 0, sizeof(get_result_response_data)); ++ ++ get_result_request_data.OemSignature[0] = 0xDB; ++ get_result_request_data.OemSignature[1] = 0x07; ++ get_result_request_data.OemSignature[2] = 0x00; ++ get_result_request_data.SubCmd = IPMI_SUB_CMD_CONTROL_REQ; ++ get_result_request_data.FirmwareType = IPMI_FW_OS; ++ ++ // TODO: we should not load files expect: grub.cfg vmlinuz and initrd ++ grub_tpcm_set_firmware_detailtype (&(get_result_request_data.FirmwareDetailType)); ++ ++ while (timeout_ms > 0) ++ { ++ response_length = sizeof (OEM_BMC_GET_RESULT_RESPONSE); ++ grub_millisleep (200); ++ timeout_ms -= 200; ++ ++ grub_dprintf ("tpcm", "get result request: request_size[%lu], response_length[%d]\n", ++ sizeof(get_result_request_data), response_length); ++ ++ status = tpcm_ipmi->excute_ipmi_cmd (tpcm_ipmi, request, &get_result_request_data, ++ sizeof(get_result_request_data), &get_result_response_data, ++ &response_length, NULL); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_dprintf ("tpcm", "excute_ipmi_cmd failed, request sub_cmd:%d, ret:%lu\n", ++ get_result_request_data.SubCmd, status); ++ continue; ++ } ++ ++ if (response_length == sizeof (OEM_BMC_GET_RESULT_RESPONSE) && \ ++ get_result_response_data.ControlResult != IPMI_MEASURE_UNKNOW) ++ { ++ grub_dprintf ("tpcm", "request ControlResult success, ControlResult:%d\n", ++ get_result_response_data.ControlResult); ++ break; ++ } ++ } ++ ++ if (get_result_response_data.ControlResult == IPMI_MEASURE_SUCCESS) ++ { ++ return GRUB_EFI_SUCCESS; ++ } ++ else if (timeout_ms <= 0) ++ { ++ grub_dprintf ("tpcm", "request TPCM constrol result timout"); ++ return GRUB_EFI_TIMEOUT; ++ } ++ ++ return GRUB_EFI_UNSUPPORTED; ++} ++ ++static grub_err_t ++grub_tpcm_log_event (unsigned char *buf, grub_size_t size, const char *description) ++{ ++ grub_err_t err = GRUB_ERR_NONE; ++ grub_efi_status_t status = GRUB_EFI_SUCCESS; ++ grub_ipmi_cmd_header request = {IPMI_BMC_LUN, ++ IPMI_NETFN_OEM, ++ IPMI_CMD_GET_MEASURE_PARM}; ++ OEM_BMC_MEASURE_REQUSET *request_data = NULL; ++ OEM_BMC_MEASURE_RESPONSE response_data; ++ ++ unsigned char output[DEFAULT_HASH_SIZE] = {0}; ++ grub_efi_uint8_t response_length = sizeof (OEM_BMC_MEASURE_RESPONSE); ++ ++ grub_memset (&response_data, 0, sizeof (response_data)); ++ ++ request_data = grub_calloc (1, sizeof (OEM_BMC_MEASURE_REQUSET)); ++ if (!request_data) ++ { ++ grub_dprintf ("tpcm", "malloc request_data failed.\n"); ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); ++ return grub_errno; ++ } ++ ++ request_data->OemSignature[0] = 0xDB; ++ request_data->OemSignature[1] = 0x07; ++ request_data->OemSignature[2] = 0x00; ++ request_data->SubCmd = IPMI_SUB_CMD_MEASURE_REQ; ++ request_data->FirmwareType = IPMI_FW_OS; ++ request_data->FirmwareHashAlgoType = IPMI_FW_HASH_SM3; ++ ++ grub_tpcm_set_firmware_detailtype (&(request_data->FirmwareDetailType)); ++ ++ status = get_firmware_hash_content (buf, size, output); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ if (permissive) ++ grub_dprintf ("tpcm", "tpcm control switch turned off, ignore get firmware hash content failure.\n"); ++ else ++ { ++ grub_printf ("get firmware hash content failed\n"); ++ err = GRUB_ERR_BUG; ++ } ++ goto fail; ++ } ++ ++ request_data->FirmwareHashLen = sizeof(extern_simple_bmeasure_req_st); ++ grub_tpcm_fillup_content (request_data, output); ++ ++ status = tpcm_ipmi->excute_ipmi_cmd (tpcm_ipmi, request, request_data, ++ sizeof (OEM_BMC_MEASURE_REQUSET), &response_data, ++ &response_length, NULL); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ if (permissive) ++ grub_dprintf ("tpcm", "tpcm control switch turned off, ignore excute_ipmi_cmd failure.\n"); ++ else ++ { ++ err = grub_error (GRUB_ERR_BUG, ++ "excute_ipmi_cmd failed, request sub_cmd:0x%x, ret:%lu\n", ++ request_data->SubCmd, status); ++ } ++ goto fail; ++ } ++ grub_dprintf ("tpcm", "send tpcm measure request success\n"); ++ ++ status = grub_tpcm_request_result (); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ if (permissive) ++ grub_dprintf ("tpcm", "tpcm control switch turned off, ignore measurement failure.\n"); ++ else ++ { ++ err = grub_error (GRUB_ERR_BAD_SIGNATURE, "bad tpcm signature"); ++ goto fail; ++ } ++ } ++ else ++ grub_dprintf ("tpcm", "tpcm hash verify success, file:%s\n", description); ++ ++ fail: ++ if (request_data) ++ { ++ grub_free (request_data); ++ } ++ return err; ++} ++ ++static grub_efi_uint8_t ++tpcm_ipmi_get_switch (void) ++{ ++ grub_efi_status_t status = GRUB_EFI_SUCCESS; ++ grub_ipmi_cmd_header request = {IPMI_BMC_LUN, ++ IPMI_NETFN_OEM, ++ IPMI_CMD_GET_MEASURE_PARM}; ++ OEM_BMC_GET_SWITCH_REQUSET request_data; ++ OEM_BMC_GET_SWITCH_RESPONSE response_data; ++ grub_efi_uint8_t response_length; ++ ++ grub_memset (&request_data, 0, sizeof (request_data)); ++ grub_memset (&response_data, 0, sizeof (response_data)); ++ ++ request_data.OemSignature[0] = 0xDB; ++ request_data.OemSignature[1] = 0x07; ++ request_data.OemSignature[2] = 0x00; ++ request_data.SubCmd = IPMI_SUB_CMD_SWITCH_REQ; ++ request_data.FirmwareType = IPMI_FW_OS; ++ request_data.FirmwareDetailType = IPMI_FW_DETAIL_GRUB_CFG; ++ ++ response_length = sizeof (OEM_BMC_GET_SWITCH_RESPONSE); ++ ++ // TODO: 确认bios接口excute_ipmi_cmd, 请求开关控制结果这块代码是否需要轮询 ++ status = tpcm_ipmi->excute_ipmi_cmd (tpcm_ipmi, request, &request_data, ++ sizeof(request_data), &response_data, ++ &response_length, NULL); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ grub_printf ("excute_ipmi_cmd failed, request sub_cmd:%d, ret:%lu\n", ++ request_data.SubCmd, status); ++ /* if we excute_ipmi_cmd, it could be the fllowing results: ++ * 1. uefi have this interface, but did not implement it. ++ * 2. uefi have implemented, but bmc did not support TPCM ++ * All of these situation should booting normally. ++ */ ++ goto out; ++ } ++ ++ if (response_data.ControlResult == IPMI_TPCM_OPEN || response_data.ControlResult == IPMI_TPCM_PERMISSIVE) ++ { ++ permissive = (response_data.ControlResult == IPMI_TPCM_PERMISSIVE) ? 1 : 0; ++ grub_dprintf ("tpcm", "tpcm: Enabled, ControlResult: %d\n", response_data.ControlResult); ++ return 1; ++ } ++ ++ out: ++ grub_dprintf ("tpcm", "tpcm: Disabled or Unknown, ControlResult: %d\n", response_data.ControlResult); ++ return 0; ++} ++ ++static grub_err_t ++tpcm_ipmi_measure (unsigned char *buf, grub_size_t size, const char *description) ++{ ++ if (tpcm_ipmi_get_switch()) ++ { ++ grub_dprintf("tpcm", "hash file: %s\n", description); ++ return grub_tpcm_log_event(buf, size, description); ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++tpcm_ipmi_write (void *context __attribute__ ((unused)), void *buf, grub_size_t size) ++{ ++ grub_err_t err; ++ err = tpcm_ipmi_measure (buf, size, context); ++ grub_tcpm_file_type = GRUB_FILE_TYPE_NONE; ++ return err; ++} ++ ++struct grub_file_verifier tpcm = ++ { ++ .name = "tpcm", ++ .init = tpcm_ipmi_init, ++ .write = tpcm_ipmi_write ++ }; ++ ++ ++GRUB_MOD_INIT(tpcm) ++{ ++ tpcm_ipmi = grub_efi_locate_protocol (&gIpmiInterfaceProtocolGuid, 0); ++ if (!tpcm_ipmi) ++ { ++ grub_dprintf ("tpcm", "locate IpmiInterfaceProtocol failed, TPCM unsupported in the machine.\n"); ++ return; ++ } ++ grub_verifier_register (&tpcm); ++} ++ ++GRUB_MOD_FINI(tpcm) ++{ ++ grub_verifier_unregister (&tpcm); ++} ++ +diff --git a/include/grub/efi/tpcm.h b/include/grub/efi/tpcm.h +new file mode 100644 +index 0000000..d4cf93b +--- /dev/null ++++ b/include/grub/efi/tpcm.h +@@ -0,0 +1,236 @@ ++#ifndef GRUB_EFI_TPCM_HEADER ++#define GRUB_EFI_TPCM_HEADER 1 ++ ++#define GRUB_EFI_HASH2_SERVICE_BINDING_PROTOCOL_GUID \ ++ { \ ++ 0xda836f8d, 0x217f, 0x4ca0, { 0x99, 0xc2, 0x1c, 0xa4, 0xe1, 0x60, 0x77, 0xea } \ ++ } ++ ++#define GRUB_EFI_HASH2_PROTOCOL_GUID \ ++ { \ ++ 0x55b1d734, 0xc5e1, 0x49db, { 0x96, 0x47, 0xb1, 0x6a, 0xfb, 0xe, 0x30, 0x5b } \ ++ } ++ ++#define EFI_TPCM_GUID \ ++ { \ ++ 0xa37e200e, 0xda90, 0x473b, { 0x8b, 0xb5, 0x1d, 0x7b, 0x11, 0xba, 0x32, 0x33 } \ ++ } ++ ++#define GRUB_HASH_ALGORITHM_SM3_GUID \ ++ { \ ++ 0x9DCD754B, 0x3479, 0x27AD, { 0x56, 0x4C, 0x68, 0x7C, 0x68, 0xEC, 0xF9, 0xB9 } \ ++ } ++ ++ ++#define OEM_SIG_SIZE 3 ++#define FIRMWARE_VERSION_SIZE 32 ++#define FIRMWARE_HASH_CONTENT_SIZE 32 ++#define FIRMWARE_NAME_SIZE 32 ++#define GRUB_IPMI_TIMEOUT_MS 2000 ++ ++// LUN ++#define IPMI_BMC_LUN 0x00 ++// Net Function Definition ++#define IPMI_NETFN_OEM 0x30 ++ ++#define IPMI_CMD_GET_MEASURE_PARM 0x92 //change a name ++ ++#define IPMI_SUB_CMD_MEASURE_REQ 0x57 //change a name ++#define IPMI_SUB_CMD_CONTROL_REQ 0x58 ++#define IPMI_SUB_CMD_SWITCH_REQ 0x59 ++ ++//bmeasure ++#define DEFAULT_HASH_SIZE 32 ++#define MEASURE_DATA_MEM_SIZE 0x100000 ++ ++#define TPCM_TAG_REQ_COMMAND 0x000000C1 ++#define TPCM_ORD_ExternSimpleBootMeasure 0x00001053 ++ ++typedef struct { ++ grub_efi_uint32_t uiCmdTag; ++ grub_efi_uint32_t uiCmdLength; ++ grub_efi_uint32_t uiCmdCode; ++ grub_efi_uint32_t uiPcr; ++ grub_efi_uint32_t uiStage; ++ grub_efi_uint8_t uaDigest[DEFAULT_HASH_SIZE]; ++ grub_efi_uint32_t uiObjLen; ++ grub_efi_uint8_t uaObj[FIRMWARE_NAME_SIZE]; ++}extern_simple_bmeasure_req_st; ++ ++typedef struct { ++ grub_efi_uint8_t OemSignature[OEM_SIG_SIZE]; ++ grub_efi_uint8_t SubCmd; ++ grub_efi_uint8_t FirmwareType; ++ grub_efi_uint8_t FirmwareDetailType; ++ grub_efi_uint8_t FirmwareHashAlgoType; ++ grub_efi_uint8_t FirmwareHashLen; ++ extern_simple_bmeasure_req_st FirmwareHashContent; ++ // reserved for kernel and initrd's version ++ grub_efi_uint8_t FirmwareVerionLen; ++ grub_efi_uint8_t FirmwareVerion[0]; ++} OEM_BMC_MEASURE_REQUSET; ++ ++typedef struct { ++ grub_efi_uint8_t CompletionCode; ++ grub_efi_uint8_t OemSignature[OEM_SIG_SIZE]; ++} OEM_BMC_MEASURE_RESPONSE; ++ ++typedef struct { ++ grub_efi_uint8_t OemSignature[OEM_SIG_SIZE]; ++ grub_efi_uint8_t SubCmd; ++ grub_efi_uint8_t FirmwareType; ++ grub_efi_uint8_t FirmwareDetailType; ++} OEM_BMC_GET_RESULT_REQUSET; ++ ++typedef struct { ++ /* In the specification of BMC <--> BIOS(GRUB2), we need CompletionCode ++ * But, BIOS has pre-processed CompletionCode in function: excute_ipmi_cmd ++ * So, we delete the word: ++ * grub_efi_uint8_t CompletionCode; ++ */ ++ grub_efi_uint8_t OemSignature[OEM_SIG_SIZE]; ++ grub_efi_uint8_t ControlResult; ++} OEM_BMC_GET_RESULT_RESPONSE; ++ ++typedef struct { ++ grub_efi_uint8_t OemSignature[OEM_SIG_SIZE]; ++ grub_efi_uint8_t SubCmd; ++ grub_efi_uint8_t FirmwareType; ++ grub_efi_uint8_t FirmwareDetailType; ++} OEM_BMC_GET_SWITCH_REQUSET; ++ ++typedef struct { ++ /* In the specification of BMC <--> BIOS(GRUB2), we need CompletionCode ++ * But, BIOS has pre-processed CompletionCode in function: excute_ipmi_cmd ++ * So, we delete the word: ++ * grub_efi_uint8_t CompletionCode; ++ */ ++ grub_efi_uint8_t OemSignature[OEM_SIG_SIZE]; ++ grub_efi_uint8_t ControlResult; ++} OEM_BMC_GET_SWITCH_RESPONSE; ++ ++typedef enum { ++ IPMI_SYSTEM_INTERFACE_UNKNOWN, // IPMI_SYSTEM_INTERFACE_TYPE->UNKNOWN ++ IPMI_SYSTEM_INTERFACE_KCS, ++ IPMI_SYSTEM_INTERFACE_SMIC, ++ IPMI_SYSTEM_INTERFACE_BT, // IPMI_SYSTEM_INTERFACE_TYPE->BT ++ IPMI_SYSTEM_INTERFACE_SSIF, ++ IPMI_SYSTEM_INTERFACE_MAX_TYPE // IPMI_SYSTEM_INTERFACE_TYPE->MAX_TYPE ++} grub_ipmi_system_interface_type; ++ ++ ++typedef struct { ++ grub_efi_uint8_t lun : 2; ++ grub_efi_uint8_t net_fn : 6; ++ grub_efi_uint8_t cmd; ++} grub_ipmi_cmd_header; ++ ++typedef enum { ++ IPMI_MEMORY, ++ IPMI_IO, // IPMI_IO ++ IPMI_MAX_INTERFACE_ADDRESS_TYPE ++} grub_ipmi_interface_address_type; ++ ++typedef enum { ++ IPMI_FW_SHIM, ++ IPMI_FW_SHIM_GRUB, ++ IPMI_FW_OS ++} grub_ipmi_firmware_type; ++ ++typedef enum { ++ IPMI_FW_DETAIL_GRUB_CFG, ++ IPMI_FW_DETAIL_KERNEL, ++ IPMI_FW_DETAIL_INITRD ++} grub_ipmi_firmware_detail_type; ++ ++typedef enum { ++ IPMI_FW_HASH_SM3, ++ IPMI_FW_HASH_RESERVED1, ++ IPMI_FW_HASH_RESERVED2 ++} grub_ipmi_firmware_hash_algo_type; ++ ++typedef enum { ++ IPMI_MEASURE_UNKNOW, ++ IPMI_MEASURE_SUCCESS, ++ IPMI_MEASURE_FAIL ++} grub_ipmi_measure_result_type; ++ ++typedef enum { ++ IPMI_TPCM_UNKNOW, ++ IPMI_TPCM_OPEN, ++ IPMI_TPCM_CLOSE, ++ IPMI_TPCM_PERMISSIVE ++} grub_ipmi_tpcm_result_type; ++ ++ ++typedef grub_efi_uint8_t EFI_MD5_HASH2[16]; ++typedef grub_efi_uint8_t EFI_SHA1_HASH2[20]; ++typedef grub_efi_uint8_t EFI_SHA224_HASH2[28]; ++typedef grub_efi_uint8_t EFI_SHA256_HASH2[32]; ++typedef grub_efi_uint8_t EFI_SHA384_HASH2[48]; ++typedef grub_efi_uint8_t EFI_SHA512_HASH2[64]; ++typedef grub_efi_uint8_t EFI_SM3_HASH2[32]; ++ ++typedef union { ++ EFI_MD5_HASH2 Md5Hash; ++ EFI_SHA1_HASH2 Sha1Hash; ++ EFI_SHA224_HASH2 Sha224Hash; ++ EFI_SHA256_HASH2 Sha256Hash; ++ EFI_SHA384_HASH2 Sha384Hash; ++ EFI_SHA512_HASH2 Sha512Hash; ++ EFI_SM3_HASH2 Sm3Hash; ++} grub_efi_hash2_output; ++ ++struct grub_efi_hash2_protocol { ++ grub_efi_status_t ++ (*get_hash_size) (struct grub_efi_hash2_protocol *this, ++ grub_efi_guid_t *hash_algorithm, ++ grub_efi_uintn_t hash_size); ++ ++ grub_efi_status_t ++ (*hash) (struct grub_efi_hash2_protocol *this, ++ grub_efi_guid_t *hash_algorithm, ++ grub_efi_uint8_t *message, ++ grub_efi_uintn_t message_size, ++ grub_efi_hash2_output *hash); ++ ++ grub_efi_status_t ++ (*hash_init) (struct grub_efi_hash2_protocol *this, ++ grub_efi_guid_t *hash_algorithm); ++ ++ grub_efi_status_t ++ (*hash_update) (struct grub_efi_hash2_protocol *this, ++ grub_efi_uint8_t *message, ++ grub_efi_uintn_t message_size); ++ ++ grub_efi_status_t ++ (*hash_final) (struct grub_efi_hash2_protocol *this, ++ grub_efi_hash2_output *hash); ++}; ++typedef struct grub_efi_hash2_protocol grub_efi_hash2_protocol_t; ++ ++struct grub_efi_ipmi_interface_protocol { ++ grub_efi_status_t ++ (*excute_ipmi_cmd) (struct grub_efi_ipmi_interface_protocol *this, ++ grub_ipmi_cmd_header request, ++ void *send_data, ++ grub_efi_uint8_t send_length, ++ void *recv_data, ++ grub_efi_uint8_t *recv_length, ++ grub_efi_uint16_t *status_codes); ++ ++ grub_ipmi_system_interface_type ++ (*get_ipmi_interface_type) (struct grub_efi_ipmi_interface_protocol *this); ++ ++ grub_efi_uint16_t ++ (*get_ipmi_base_address) (struct grub_efi_ipmi_interface_protocol *this); ++ ++ grub_ipmi_interface_address_type ++ (*get_ipmi_base_address_type) (struct grub_efi_ipmi_interface_protocol *this); ++ ++ grub_efi_uint8_t ++ (*get_ipmi_version) (struct grub_efi_ipmi_interface_protocol *this); ++}; ++typedef struct grub_efi_ipmi_interface_protocol grub_efi_ipmi_interface_protocol_t; ++ ++#endif +-- +2.27.0 + diff --git a/grub.macros b/grub.macros index d5da50a..c240136 100644 --- a/grub.macros +++ b/grub.macros @@ -118,7 +118,7 @@ ### fixme %ifarch aarch64 %{arm} riscv64 loongarch64 -%global efi_modules " tpm " +%global efi_modules " tpm tpcm_kunpeng " %else %global efi_modules " backtrace chain tpm usb usbserial_common usbserial_pl2303 usbserial_ftdi usbserial_usbdebug keylayouts at_keyboard " %endif diff --git a/grub.patches b/grub.patches index 9a45129..bbd839d 100644 --- a/grub.patches +++ b/grub.patches @@ -341,3 +341,5 @@ Patch0341: backport-fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-ind.patch Patch0342: backport-fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch Patch0343: backport-fs-ntfs-Make-code-more-readable.patch Patch0344: 1008-loongarch-Disable-relaxation-relocations.patch +Patch0345: add-TPCM-support-with-ipmi-channel.patch +Patch0346: skip-verification-when-not-loading-grub.cfg.patch diff --git a/grub2.spec b/grub2.spec index a43e984..ba32715 100644 --- a/grub2.spec +++ b/grub2.spec @@ -14,7 +14,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 39 +Release: 40 Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -440,6 +440,14 @@ fi %{_datadir}/man/man* %changelog +* Fri Jan 12 2024 zhangqiumiao - 1:2.06-40 +- Type:requirement +- CVE:NA +- SUG:NA +- DESC:add TPCM support with ipmi channel + change the name of module tpcm to tpcm_kunpeng + skip verification when not loading grub.cfg + * Tue Dec 5 2023 mengyingkun - 1:2.06-39 - Type:requirement - CVE:NA diff --git a/skip-verification-when-not-loading-grub.cfg.patch b/skip-verification-when-not-loading-grub.cfg.patch new file mode 100644 index 0000000..6928000 --- /dev/null +++ b/skip-verification-when-not-loading-grub.cfg.patch @@ -0,0 +1,29 @@ +From c8b6446348a445a51024d04b2e8e5b417c3a1f73 Mon Sep 17 00:00:00 2001 +From: Qiumiao Zhang +Date: Wed, 31 May 2023 15:13:07 +0800 +Subject: [PATCH] skip verification when not loading grub.cfg + +Skip verification when just opening the grub.cfg without loading it. +There is no need to verify grub.cfg twice when tpcm is enabled. + +Signed-off-by: Qiumiao Zhang +--- + grub-core/normal/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index b72fe3d..8ce5a60 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -369,7 +369,7 @@ grub_try_normal_prefix (const char *prefix) + if (config) + { + grub_file_t file; +- file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG); ++ file = grub_file_open (config, GRUB_FILE_TYPE_SKIP_SIGNATURE); + if (file) + { + grub_file_close (file); +-- +2.27.0 + -- Gitee