15ca02815Sjsg /*
25ca02815Sjsg * Copyright 2020 Advanced Micro Devices, Inc.
35ca02815Sjsg *
45ca02815Sjsg * Permission is hereby granted, free of charge, to any person obtaining a
55ca02815Sjsg * copy of this software and associated documentation files (the "Software"),
65ca02815Sjsg * to deal in the Software without restriction, including without limitation
75ca02815Sjsg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
85ca02815Sjsg * and/or sell copies of the Software, and to permit persons to whom the
95ca02815Sjsg * Software is furnished to do so, subject to the following conditions:
105ca02815Sjsg *
115ca02815Sjsg * The above copyright notice and this permission notice shall be included in
125ca02815Sjsg * all copies or substantial portions of the Software.
135ca02815Sjsg *
145ca02815Sjsg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
155ca02815Sjsg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
165ca02815Sjsg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
175ca02815Sjsg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
185ca02815Sjsg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
195ca02815Sjsg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
205ca02815Sjsg * OTHER DEALINGS IN THE SOFTWARE.
215ca02815Sjsg *
225ca02815Sjsg */
235ca02815Sjsg
245ca02815Sjsg #include <linux/debugfs.h>
255ca02815Sjsg #include <linux/firmware.h>
265ca02815Sjsg #include <linux/dma-mapping.h>
275ca02815Sjsg
285ca02815Sjsg #include "amdgpu.h"
295ca02815Sjsg #include "amdgpu_fw_attestation.h"
305ca02815Sjsg #include "amdgpu_psp.h"
315ca02815Sjsg #include "amdgpu_ucode.h"
325ca02815Sjsg #include "soc15_common.h"
335ca02815Sjsg
345ca02815Sjsg #define FW_ATTESTATION_DB_COOKIE 0x143b6a37
355ca02815Sjsg #define FW_ATTESTATION_RECORD_VALID 1
365ca02815Sjsg #define FW_ATTESTATION_MAX_SIZE 4096
375ca02815Sjsg
38*f005ef32Sjsg struct FW_ATT_DB_HEADER {
395ca02815Sjsg uint32_t AttDbVersion; /* version of the fwar feature */
405ca02815Sjsg uint32_t AttDbCookie; /* cookie as an extra check for corrupt data */
41*f005ef32Sjsg };
425ca02815Sjsg
43*f005ef32Sjsg struct FW_ATT_RECORD {
445ca02815Sjsg uint16_t AttFwIdV1; /* Legacy FW Type field */
455ca02815Sjsg uint16_t AttFwIdV2; /* V2 FW ID field */
465ca02815Sjsg uint32_t AttFWVersion; /* FW Version */
475ca02815Sjsg uint16_t AttFWActiveFunctionID; /* The VF ID (only in VF Attestation Table) */
485ca02815Sjsg uint8_t AttSource; /* FW source indicator */
495ca02815Sjsg uint8_t RecordValid; /* Indicates whether the record is a valid entry */
505ca02815Sjsg uint32_t AttFwTaId; /* Ta ID (only in TA Attestation Table) */
51*f005ef32Sjsg };
525ca02815Sjsg
amdgpu_fw_attestation_debugfs_read(struct file * f,char __user * buf,size_t size,loff_t * pos)535ca02815Sjsg static ssize_t amdgpu_fw_attestation_debugfs_read(struct file *f,
545ca02815Sjsg char __user *buf,
555ca02815Sjsg size_t size,
565ca02815Sjsg loff_t *pos)
575ca02815Sjsg {
585ca02815Sjsg STUB();
595ca02815Sjsg return -ENOSYS;
605ca02815Sjsg #ifdef notyet
615ca02815Sjsg struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
625ca02815Sjsg uint64_t records_addr = 0;
635ca02815Sjsg uint64_t vram_pos = 0;
64*f005ef32Sjsg struct FW_ATT_DB_HEADER fw_att_hdr = {0};
65*f005ef32Sjsg struct FW_ATT_RECORD fw_att_record = {0};
665ca02815Sjsg
67*f005ef32Sjsg if (size < sizeof(struct FW_ATT_RECORD)) {
685ca02815Sjsg DRM_WARN("FW attestation input buffer not enough memory");
695ca02815Sjsg return -EINVAL;
705ca02815Sjsg }
715ca02815Sjsg
72*f005ef32Sjsg if ((*pos + sizeof(struct FW_ATT_DB_HEADER)) >= FW_ATTESTATION_MAX_SIZE) {
735ca02815Sjsg DRM_WARN("FW attestation out of bounds");
745ca02815Sjsg return 0;
755ca02815Sjsg }
765ca02815Sjsg
775ca02815Sjsg if (psp_get_fw_attestation_records_addr(&adev->psp, &records_addr)) {
785ca02815Sjsg DRM_WARN("Failed to get FW attestation record address");
795ca02815Sjsg return -EINVAL;
805ca02815Sjsg }
815ca02815Sjsg
825ca02815Sjsg vram_pos = records_addr - adev->gmc.vram_start;
835ca02815Sjsg
845ca02815Sjsg if (*pos == 0) {
855ca02815Sjsg amdgpu_device_vram_access(adev,
865ca02815Sjsg vram_pos,
875ca02815Sjsg (uint32_t *)&fw_att_hdr,
88*f005ef32Sjsg sizeof(struct FW_ATT_DB_HEADER),
895ca02815Sjsg false);
905ca02815Sjsg
915ca02815Sjsg if (fw_att_hdr.AttDbCookie != FW_ATTESTATION_DB_COOKIE) {
925ca02815Sjsg DRM_WARN("Invalid FW attestation cookie");
935ca02815Sjsg return -EINVAL;
945ca02815Sjsg }
955ca02815Sjsg
965ca02815Sjsg DRM_INFO("FW attestation version = 0x%X", fw_att_hdr.AttDbVersion);
975ca02815Sjsg }
985ca02815Sjsg
995ca02815Sjsg amdgpu_device_vram_access(adev,
100*f005ef32Sjsg vram_pos + sizeof(struct FW_ATT_DB_HEADER) + *pos,
1015ca02815Sjsg (uint32_t *)&fw_att_record,
102*f005ef32Sjsg sizeof(struct FW_ATT_RECORD),
1035ca02815Sjsg false);
1045ca02815Sjsg
1055ca02815Sjsg if (fw_att_record.RecordValid != FW_ATTESTATION_RECORD_VALID)
1065ca02815Sjsg return 0;
1075ca02815Sjsg
108*f005ef32Sjsg if (copy_to_user(buf, (void *)&fw_att_record, sizeof(struct FW_ATT_RECORD)))
1095ca02815Sjsg return -EINVAL;
1105ca02815Sjsg
111*f005ef32Sjsg *pos += sizeof(struct FW_ATT_RECORD);
1125ca02815Sjsg
113*f005ef32Sjsg return sizeof(struct FW_ATT_RECORD);
1145ca02815Sjsg #endif
1155ca02815Sjsg }
1165ca02815Sjsg
1175ca02815Sjsg #ifdef notyet
1185ca02815Sjsg static const struct file_operations amdgpu_fw_attestation_debugfs_ops = {
1195ca02815Sjsg .owner = THIS_MODULE,
1205ca02815Sjsg .read = amdgpu_fw_attestation_debugfs_read,
1215ca02815Sjsg .write = NULL,
1225ca02815Sjsg .llseek = default_llseek
1235ca02815Sjsg };
1245ca02815Sjsg #endif
1255ca02815Sjsg
amdgpu_is_fw_attestation_supported(struct amdgpu_device * adev)1265ca02815Sjsg static int amdgpu_is_fw_attestation_supported(struct amdgpu_device *adev)
1275ca02815Sjsg {
1285ca02815Sjsg if (adev->flags & AMD_IS_APU)
1295ca02815Sjsg return 0;
1305ca02815Sjsg
1315ca02815Sjsg if (adev->asic_type >= CHIP_SIENNA_CICHLID)
1325ca02815Sjsg return 1;
1335ca02815Sjsg
1345ca02815Sjsg return 0;
1355ca02815Sjsg }
1365ca02815Sjsg
amdgpu_fw_attestation_debugfs_init(struct amdgpu_device * adev)1375ca02815Sjsg void amdgpu_fw_attestation_debugfs_init(struct amdgpu_device *adev)
1385ca02815Sjsg {
1395ca02815Sjsg if (!amdgpu_is_fw_attestation_supported(adev))
1405ca02815Sjsg return;
1415ca02815Sjsg
1425ca02815Sjsg debugfs_create_file("amdgpu_fw_attestation",
143*f005ef32Sjsg 0400,
1445ca02815Sjsg adev_to_drm(adev)->primary->debugfs_root,
1455ca02815Sjsg adev,
1465ca02815Sjsg &amdgpu_fw_attestation_debugfs_ops);
1475ca02815Sjsg }
148