0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/kernel.h>
0011 #include <linux/slab.h>
0012
0013 #include "nfp.h"
0014 #include "nfp_cpp.h"
0015 #include "nfp_nffw.h"
0016
0017 #define NFP_MIP_SIGNATURE cpu_to_le32(0x0050494d)
0018 #define NFP_MIP_VERSION cpu_to_le32(1)
0019 #define NFP_MIP_MAX_OFFSET (256 * 1024)
0020
0021 struct nfp_mip {
0022 __le32 signature;
0023 __le32 mip_version;
0024 __le32 mip_size;
0025 __le32 first_entry;
0026
0027 __le32 version;
0028 __le32 buildnum;
0029 __le32 buildtime;
0030 __le32 loadtime;
0031
0032 __le32 symtab_addr;
0033 __le32 symtab_size;
0034 __le32 strtab_addr;
0035 __le32 strtab_size;
0036
0037 char name[16];
0038 char toolchain[32];
0039 };
0040
0041
0042 static int
0043 nfp_mip_try_read(struct nfp_cpp *cpp, u32 cpp_id, u64 addr, struct nfp_mip *mip)
0044 {
0045 int ret;
0046
0047 ret = nfp_cpp_read(cpp, cpp_id, addr, mip, sizeof(*mip));
0048 if (ret != sizeof(*mip)) {
0049 nfp_err(cpp, "Failed to read MIP data (%d, %zu)\n",
0050 ret, sizeof(*mip));
0051 return -EIO;
0052 }
0053 if (mip->signature != NFP_MIP_SIGNATURE) {
0054 nfp_warn(cpp, "Incorrect MIP signature (0x%08x)\n",
0055 le32_to_cpu(mip->signature));
0056 return -EINVAL;
0057 }
0058 if (mip->mip_version != NFP_MIP_VERSION) {
0059 nfp_warn(cpp, "Unsupported MIP version (%d)\n",
0060 le32_to_cpu(mip->mip_version));
0061 return -EINVAL;
0062 }
0063
0064 return 0;
0065 }
0066
0067
0068 static int nfp_mip_read_resource(struct nfp_cpp *cpp, struct nfp_mip *mip)
0069 {
0070 struct nfp_nffw_info *nffw_info;
0071 u32 cpp_id;
0072 u64 addr;
0073 int err;
0074
0075 nffw_info = nfp_nffw_info_open(cpp);
0076 if (IS_ERR(nffw_info))
0077 return PTR_ERR(nffw_info);
0078
0079 err = nfp_nffw_info_mip_first(nffw_info, &cpp_id, &addr);
0080 if (err)
0081 goto exit_close_nffw;
0082
0083 err = nfp_mip_try_read(cpp, cpp_id, addr, mip);
0084 exit_close_nffw:
0085 nfp_nffw_info_close(nffw_info);
0086 return err;
0087 }
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099 const struct nfp_mip *nfp_mip_open(struct nfp_cpp *cpp)
0100 {
0101 struct nfp_mip *mip;
0102 int err;
0103
0104 mip = kmalloc(sizeof(*mip), GFP_KERNEL);
0105 if (!mip)
0106 return NULL;
0107
0108 err = nfp_mip_read_resource(cpp, mip);
0109 if (err) {
0110 kfree(mip);
0111 return NULL;
0112 }
0113
0114 mip->name[sizeof(mip->name) - 1] = 0;
0115
0116 return mip;
0117 }
0118
0119 void nfp_mip_close(const struct nfp_mip *mip)
0120 {
0121 kfree(mip);
0122 }
0123
0124 const char *nfp_mip_name(const struct nfp_mip *mip)
0125 {
0126 return mip->name;
0127 }
0128
0129
0130
0131
0132
0133
0134
0135 void nfp_mip_symtab(const struct nfp_mip *mip, u32 *addr, u32 *size)
0136 {
0137 *addr = le32_to_cpu(mip->symtab_addr);
0138 *size = le32_to_cpu(mip->symtab_size);
0139 }
0140
0141
0142
0143
0144
0145
0146
0147 void nfp_mip_strtab(const struct nfp_mip *mip, u32 *addr, u32 *size)
0148 {
0149 *addr = le32_to_cpu(mip->strtab_addr);
0150 *size = le32_to_cpu(mip->strtab_size);
0151 }