1 /* 2 * Copyright (C) 2015-2017 Netronome Systems, Inc. 3 * 4 * This software is dual licensed under the GNU General License Version 2, 5 * June 1991 as shown in the file COPYING in the top-level directory of this 6 * source tree or the BSD 2-Clause License provided below. You have the 7 * option to license this software under the complete terms of either license. 8 * 9 * The BSD 2-Clause License: 10 * 11 * Redistribution and use in source and binary forms, with or 12 * without modification, are permitted provided that the following 13 * conditions are met: 14 * 15 * 1. Redistributions of source code must retain the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer. 18 * 19 * 2. Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials 22 * provided with the distribution. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 * SOFTWARE. 32 */ 33 34 /* 35 * nfp_mip.c 36 * Authors: Jakub Kicinski <jakub.kicinski@netronome.com> 37 * Jason McMullan <jason.mcmullan@netronome.com> 38 * Espen Skoglund <espen.skoglund@netronome.com> 39 */ 40 #include <linux/kernel.h> 41 #include <linux/slab.h> 42 43 #include "nfp.h" 44 #include "nfp_cpp.h" 45 #include "nfp_nffw.h" 46 47 #define NFP_MIP_SIGNATURE cpu_to_le32(0x0050494d) /* "MIP\0" */ 48 #define NFP_MIP_VERSION cpu_to_le32(1) 49 #define NFP_MIP_MAX_OFFSET (256 * 1024) 50 51 struct nfp_mip { 52 __le32 signature; 53 __le32 mip_version; 54 __le32 mip_size; 55 __le32 first_entry; 56 57 __le32 version; 58 __le32 buildnum; 59 __le32 buildtime; 60 __le32 loadtime; 61 62 __le32 symtab_addr; 63 __le32 symtab_size; 64 __le32 strtab_addr; 65 __le32 strtab_size; 66 67 char name[16]; 68 char toolchain[32]; 69 }; 70 71 /* Read memory and check if it could be a valid MIP */ 72 static int 73 nfp_mip_try_read(struct nfp_cpp *cpp, u32 cpp_id, u64 addr, struct nfp_mip *mip) 74 { 75 int ret; 76 77 ret = nfp_cpp_read(cpp, cpp_id, addr, mip, sizeof(*mip)); 78 if (ret != sizeof(*mip)) { 79 nfp_err(cpp, "Failed to read MIP data (%d, %zu)\n", 80 ret, sizeof(*mip)); 81 return -EIO; 82 } 83 if (mip->signature != NFP_MIP_SIGNATURE) { 84 nfp_warn(cpp, "Incorrect MIP signature (0x%08x)\n", 85 le32_to_cpu(mip->signature)); 86 return -EINVAL; 87 } 88 if (mip->mip_version != NFP_MIP_VERSION) { 89 nfp_warn(cpp, "Unsupported MIP version (%d)\n", 90 le32_to_cpu(mip->mip_version)); 91 return -EINVAL; 92 } 93 94 return 0; 95 } 96 97 /* Try to locate MIP using the resource table */ 98 static int nfp_mip_read_resource(struct nfp_cpp *cpp, struct nfp_mip *mip) 99 { 100 struct nfp_nffw_info *nffw_info; 101 u32 cpp_id; 102 u64 addr; 103 int err; 104 105 nffw_info = nfp_nffw_info_open(cpp); 106 if (IS_ERR(nffw_info)) 107 return PTR_ERR(nffw_info); 108 109 err = nfp_nffw_info_mip_first(nffw_info, &cpp_id, &addr); 110 if (err) 111 goto exit_close_nffw; 112 113 err = nfp_mip_try_read(cpp, cpp_id, addr, mip); 114 exit_close_nffw: 115 nfp_nffw_info_close(nffw_info); 116 return err; 117 } 118 119 /** 120 * nfp_mip_open() - Get device MIP structure 121 * @cpp: NFP CPP Handle 122 * 123 * Copy MIP structure from NFP device and return it. The returned 124 * structure is handled internally by the library and should be 125 * freed by calling nfp_mip_close(). 126 * 127 * Return: pointer to mip, NULL on failure. 128 */ 129 const struct nfp_mip *nfp_mip_open(struct nfp_cpp *cpp) 130 { 131 struct nfp_mip *mip; 132 int err; 133 134 mip = kmalloc(sizeof(*mip), GFP_KERNEL); 135 if (!mip) 136 return NULL; 137 138 err = nfp_mip_read_resource(cpp, mip); 139 if (err) { 140 kfree(mip); 141 return NULL; 142 } 143 144 mip->name[sizeof(mip->name) - 1] = 0; 145 146 return mip; 147 } 148 149 void nfp_mip_close(const struct nfp_mip *mip) 150 { 151 kfree(mip); 152 } 153 154 const char *nfp_mip_name(const struct nfp_mip *mip) 155 { 156 return mip->name; 157 } 158 159 /** 160 * nfp_mip_symtab() - Get the address and size of the MIP symbol table 161 * @mip: MIP handle 162 * @addr: Location for NFP DDR address of MIP symbol table 163 * @size: Location for size of MIP symbol table 164 */ 165 void nfp_mip_symtab(const struct nfp_mip *mip, u32 *addr, u32 *size) 166 { 167 *addr = le32_to_cpu(mip->symtab_addr); 168 *size = le32_to_cpu(mip->symtab_size); 169 } 170 171 /** 172 * nfp_mip_strtab() - Get the address and size of the MIP symbol name table 173 * @mip: MIP handle 174 * @addr: Location for NFP DDR address of MIP symbol name table 175 * @size: Location for size of MIP symbol name table 176 */ 177 void nfp_mip_strtab(const struct nfp_mip *mip, u32 *addr, u32 *size) 178 { 179 *addr = le32_to_cpu(mip->strtab_addr); 180 *size = le32_to_cpu(mip->strtab_size); 181 } 182