1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * Copyright 2021 OmniOS Community Edition (OmniOSce) Association. 27 * Copyright 2025 Oxide Computer Company 28 */ 29 30 #include <sys/types.h> 31 #include <sys/ucode.h> 32 #include <sys/ucode_amd.h> 33 #include <sys/stdbool.h> 34 #ifdef _KERNEL 35 #include <sys/systm.h> 36 #else 37 #include <strings.h> 38 #endif 39 40 /* 41 * Perform basic validation of an AMD microcode container file. 42 */ 43 ucode_errno_t 44 ucode_validate_amd(uint8_t *ucodep, size_t size) 45 { 46 uint8_t *ptr = ucodep; 47 bool first = true; 48 uint32_t magic; 49 50 if (ucodep == NULL || size <= 0) 51 return (EM_INVALIDARG); 52 53 /* Magic Number */ 54 bcopy(ptr, &magic, sizeof (magic)); 55 if (magic != UCODE_AMD_CONTAINER_MAGIC) 56 return (EM_FILEFORMAT); 57 ptr += sizeof (magic); 58 size -= sizeof (magic); 59 60 /* 61 * There follow one or more TLV-encoded sections. We expect that the 62 * first section is an equivalence table and all subsequent sections 63 * are patches and return EM_FILEFORMAT if that is not the case. 64 */ 65 while (size > sizeof (ucode_section_amd_t)) { 66 ucode_section_amd_t section; 67 68 bcopy(ptr, §ion, sizeof (section)); 69 if (section.usa_size == 0 || section.usa_size > size) 70 return (EM_FILEFORMAT); 71 ptr += sizeof (section); 72 size -= sizeof (section); 73 74 switch (section.usa_type) { 75 case UCODE_AMD_CONTAINER_TYPE_EQUIV: 76 if (!first) 77 return (EM_FILEFORMAT); 78 /* 79 * The equivalence table maps processor IDs (family, 80 * stepping, model) to a Microcode Patch Equivalent 81 * Processor ID. We just verify that it its size is a 82 * whole number of entries. 83 */ 84 if (section.usa_size % sizeof (ucode_eqtbl_amd_t) != 0) 85 return (EM_FILEFORMAT); 86 break; 87 88 case UCODE_AMD_CONTAINER_TYPE_PATCH: 89 if (first) 90 return (EM_FILEFORMAT); 91 break; 92 93 default: 94 return (EM_FILEFORMAT); 95 } 96 97 size -= section.usa_size; 98 ptr += section.usa_size; 99 first = false; 100 } 101 102 /* We don't expect there to be any unaccounted for trailing data */ 103 if (size != 0) 104 return (EM_FILEFORMAT); 105 106 return (EM_OK); 107 } 108