Commit f716113a authored by Alex Deucher's avatar Alex Deucher

drm/amdgpu/discovery: add additional validation

Check the table signatures and checksums and verify that
the tables exist before accessing them.

v2: disable MALL table for now
Acked-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 24681cb5
...@@ -271,8 +271,6 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev) ...@@ -271,8 +271,6 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
{ {
struct table_info *info; struct table_info *info;
struct binary_header *bhdr; struct binary_header *bhdr;
struct ip_discovery_header *ihdr;
struct gpu_info_header *ghdr;
uint16_t offset; uint16_t offset;
uint16_t size; uint16_t size;
uint16_t checksum; uint16_t checksum;
...@@ -290,7 +288,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev) ...@@ -290,7 +288,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
goto out; goto out;
} }
if(!amdgpu_discovery_verify_binary_signature(adev->mman.discovery_bin)) { if (!amdgpu_discovery_verify_binary_signature(adev->mman.discovery_bin)) {
dev_warn(adev->dev, "get invalid ip discovery binary signature from vram\n"); dev_warn(adev->dev, "get invalid ip discovery binary signature from vram\n");
/* retry read ip discovery binary from file */ /* retry read ip discovery binary from file */
r = amdgpu_discovery_read_binary_from_file(adev, adev->mman.discovery_bin); r = amdgpu_discovery_read_binary_from_file(adev, adev->mman.discovery_bin);
...@@ -324,31 +322,110 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev) ...@@ -324,31 +322,110 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
info = &bhdr->table_list[IP_DISCOVERY]; info = &bhdr->table_list[IP_DISCOVERY];
offset = le16_to_cpu(info->offset); offset = le16_to_cpu(info->offset);
checksum = le16_to_cpu(info->checksum); checksum = le16_to_cpu(info->checksum);
ihdr = (struct ip_discovery_header *)(adev->mman.discovery_bin + offset);
if (le32_to_cpu(ihdr->signature) != DISCOVERY_TABLE_SIGNATURE) { if (offset) {
dev_err(adev->dev, "invalid ip discovery data table signature\n"); struct ip_discovery_header *ihdr =
r = -EINVAL; (struct ip_discovery_header *)(adev->mman.discovery_bin + offset);
goto out; if (le32_to_cpu(ihdr->signature) != DISCOVERY_TABLE_SIGNATURE) {
} dev_err(adev->dev, "invalid ip discovery data table signature\n");
r = -EINVAL;
goto out;
}
if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset, if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,
le16_to_cpu(ihdr->size), checksum)) { le16_to_cpu(ihdr->size), checksum)) {
dev_err(adev->dev, "invalid ip discovery data table checksum\n"); dev_err(adev->dev, "invalid ip discovery data table checksum\n");
r = -EINVAL; r = -EINVAL;
goto out; goto out;
}
} }
info = &bhdr->table_list[GC]; info = &bhdr->table_list[GC];
offset = le16_to_cpu(info->offset); offset = le16_to_cpu(info->offset);
checksum = le16_to_cpu(info->checksum); checksum = le16_to_cpu(info->checksum);
ghdr = (struct gpu_info_header *)(adev->mman.discovery_bin + offset);
if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset, if (offset) {
le32_to_cpu(ghdr->size), checksum)) { struct gpu_info_header *ghdr =
dev_err(adev->dev, "invalid gc data table checksum\n"); (struct gpu_info_header *)(adev->mman.discovery_bin + offset);
r = -EINVAL;
goto out; if (le32_to_cpu(ghdr->table_id) != GC_TABLE_ID) {
dev_err(adev->dev, "invalid ip discovery gc table id\n");
r = -EINVAL;
goto out;
}
if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,
le32_to_cpu(ghdr->size), checksum)) {
dev_err(adev->dev, "invalid gc data table checksum\n");
r = -EINVAL;
goto out;
}
}
info = &bhdr->table_list[HARVEST_INFO];
offset = le16_to_cpu(info->offset);
checksum = le16_to_cpu(info->checksum);
if (offset) {
struct harvest_info_header *hhdr =
(struct harvest_info_header *)(adev->mman.discovery_bin + offset);
if (le32_to_cpu(hhdr->signature) != HARVEST_TABLE_SIGNATURE) {
dev_err(adev->dev, "invalid ip discovery harvest table signature\n");
r = -EINVAL;
goto out;
}
if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,
sizeof(struct harvest_table), checksum)) {
dev_err(adev->dev, "invalid harvest data table checksum\n");
r = -EINVAL;
goto out;
}
}
info = &bhdr->table_list[VCN_INFO];
offset = le16_to_cpu(info->offset);
checksum = le16_to_cpu(info->checksum);
if (offset) {
struct vcn_info_header *vhdr =
(struct vcn_info_header *)(adev->mman.discovery_bin + offset);
if (le32_to_cpu(vhdr->table_id) != VCN_INFO_TABLE_ID) {
dev_err(adev->dev, "invalid ip discovery vcn table id\n");
r = -EINVAL;
goto out;
}
if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,
le32_to_cpu(vhdr->size_bytes), checksum)) {
dev_err(adev->dev, "invalid vcn data table checksum\n");
r = -EINVAL;
goto out;
}
}
info = &bhdr->table_list[MALL_INFO];
offset = le16_to_cpu(info->offset);
checksum = le16_to_cpu(info->checksum);
if (0 && offset) {
struct mall_info_header *mhdr =
(struct mall_info_header *)(adev->mman.discovery_bin + offset);
if (le32_to_cpu(mhdr->table_id) != MALL_INFO_TABLE_ID) {
dev_err(adev->dev, "invalid ip discovery mall table id\n");
r = -EINVAL;
goto out;
}
if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,
le32_to_cpu(mhdr->size_bytes), checksum)) {
dev_err(adev->dev, "invalid mall data table checksum\n");
r = -EINVAL;
goto out;
}
} }
return 0; return 0;
...@@ -441,11 +518,19 @@ static void amdgpu_discovery_read_from_harvest_table(struct amdgpu_device *adev, ...@@ -441,11 +518,19 @@ static void amdgpu_discovery_read_from_harvest_table(struct amdgpu_device *adev,
{ {
struct binary_header *bhdr; struct binary_header *bhdr;
struct harvest_table *harvest_info; struct harvest_table *harvest_info;
u16 offset;
int i; int i;
bhdr = (struct binary_header *)adev->mman.discovery_bin; bhdr = (struct binary_header *)adev->mman.discovery_bin;
harvest_info = (struct harvest_table *)(adev->mman.discovery_bin + offset = le16_to_cpu(bhdr->table_list[HARVEST_INFO].offset);
le16_to_cpu(bhdr->table_list[HARVEST_INFO].offset));
if (!offset) {
dev_err(adev->dev, "invalid harvest table offset\n");
return;
}
harvest_info = (struct harvest_table *)(adev->mman.discovery_bin + offset);
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
if (le16_to_cpu(harvest_info->list[i].hw_id) == 0) if (le16_to_cpu(harvest_info->list[i].hw_id) == 0)
break; break;
...@@ -1176,6 +1261,7 @@ int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev) ...@@ -1176,6 +1261,7 @@ int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev)
{ {
struct binary_header *bhdr; struct binary_header *bhdr;
union gc_info *gc_info; union gc_info *gc_info;
u16 offset;
if (!adev->mman.discovery_bin) { if (!adev->mman.discovery_bin) {
DRM_ERROR("ip discovery uninitialized\n"); DRM_ERROR("ip discovery uninitialized\n");
...@@ -1183,8 +1269,15 @@ int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev) ...@@ -1183,8 +1269,15 @@ int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev)
} }
bhdr = (struct binary_header *)adev->mman.discovery_bin; bhdr = (struct binary_header *)adev->mman.discovery_bin;
gc_info = (union gc_info *)(adev->mman.discovery_bin + offset = le16_to_cpu(bhdr->table_list[GC].offset);
le16_to_cpu(bhdr->table_list[GC].offset));
if (!offset) {
dev_err(adev->dev, "invalid GC table offset\n");
return -EINVAL;
}
gc_info = (union gc_info *)(adev->mman.discovery_bin + offset);
switch (le16_to_cpu(gc_info->v1.header.version_major)) { switch (le16_to_cpu(gc_info->v1.header.version_major)) {
case 1: case 1:
adev->gfx.config.max_shader_engines = le32_to_cpu(gc_info->v1.gc_num_se); adev->gfx.config.max_shader_engines = le32_to_cpu(gc_info->v1.gc_num_se);
...@@ -1260,6 +1353,7 @@ int amdgpu_discovery_get_mall_info(struct amdgpu_device *adev) ...@@ -1260,6 +1353,7 @@ int amdgpu_discovery_get_mall_info(struct amdgpu_device *adev)
union mall_info *mall_info; union mall_info *mall_info;
u32 u, mall_size_per_umc, m_s_present, half_use; u32 u, mall_size_per_umc, m_s_present, half_use;
u64 mall_size; u64 mall_size;
u16 offset;
if (!adev->mman.discovery_bin) { if (!adev->mman.discovery_bin) {
DRM_ERROR("ip discovery uninitialized\n"); DRM_ERROR("ip discovery uninitialized\n");
...@@ -1267,8 +1361,14 @@ int amdgpu_discovery_get_mall_info(struct amdgpu_device *adev) ...@@ -1267,8 +1361,14 @@ int amdgpu_discovery_get_mall_info(struct amdgpu_device *adev)
} }
bhdr = (struct binary_header *)adev->mman.discovery_bin; bhdr = (struct binary_header *)adev->mman.discovery_bin;
mall_info = (union mall_info *)(adev->mman.discovery_bin + offset = le16_to_cpu(bhdr->table_list[MALL_INFO].offset);
le16_to_cpu(bhdr->table_list[MALL_INFO].offset));
if (!offset) {
dev_err(adev->dev, "invalid mall table offset\n");
return -EINVAL;
}
mall_info = (union mall_info *)(adev->mman.discovery_bin + offset);
switch (le16_to_cpu(mall_info->v1.header.version_major)) { switch (le16_to_cpu(mall_info->v1.header.version_major)) {
case 1: case 1:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment