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 2023 Oxide Computer Company 28 */ 29 30 #include <sys/types.h> 31 #include <sys/ucode.h> 32 #include <sys/ucode_amd.h> 33 #ifdef _KERNEL 34 #include <sys/systm.h> 35 #else 36 #include <strings.h> 37 #endif 38 39 /* 40 * Perform basic validation of an AMD microcode bundle file. 41 */ 42 ucode_errno_t 43 ucode_validate_amd(uint8_t *ucodep, int size) 44 { 45 uint32_t *ptr = (uint32_t *)ucodep; 46 uint32_t count; 47 48 if (ucodep == NULL || size <= 0) 49 return (EM_INVALIDARG); 50 51 /* Magic Number: "AMD\0" */ 52 size -= 4; 53 if (*ptr++ != 0x00414d44) 54 return (EM_FILEFORMAT); 55 56 /* 57 * There follows an equivalence table that maps processor IDs (family, 58 * stepping, model) to a Microcode Patch Equivalent Processor ID. 59 * The format of the equivalence table is: 60 * 0-3 version? - always 0 61 * 4-7 count - number of entries in table, including terminator 62 * < 16 byte record > * (count - 1) 63 * < 16 byte terminating record, all zeros > 64 */ 65 size -= 4; 66 if (*ptr++ != 0) 67 return (EM_FILEFORMAT); 68 69 size -= 4; 70 count = *ptr++; 71 if (count > size || count % 16 != 0) 72 return (EM_FILEFORMAT); 73 74 /* Skip past equivalence table and the terminating record */ 75 ptr = (uint32_t *)(((uint8_t *)ptr) + count); 76 size -= count; 77 78 /* 79 * There then follow one or more microcode patches in the following 80 * format: 81 * 0-3 patch type 82 * 4-7 patch length 83 * < length bytes > 84 */ 85 while (size > 8) { 86 /* We only support patch type 1 */ 87 size -= 4; 88 if (*ptr++ != 1) 89 return (EM_FILEFORMAT); 90 91 size -= 4; 92 if (((count = *ptr++) > size)) 93 return (EM_FILEFORMAT); 94 95 ptr = (uint32_t *)(((uint8_t *)ptr) + count); 96 size -= count; 97 } 98 99 if (size != 0) 100 return (EM_FILEFORMAT); 101 102 return (EM_OK); 103 } 104