From bcb77a13cbe3fb7958cc2ce1f54854cdccf1daf9 Mon Sep 17 00:00:00 2001 From: "Kenny L. Ku" Date: Tue, 8 Oct 2019 16:21:01 -0700 Subject: Update peci_cmds with RdEndPointConfig and WrEndPointConfig support - update peci_cmds with Endpoint PCI/Local read/write support - update peci_cmds with MMIO read support Tested: - Manually tested using peci_cmds Signed-off-by: Kenny K. Ku Change-Id: Iddd62bd458d4a11c36dfc43fb966ba2283be800d --- libpeci/peci.c | 75 +++++++++++++++++ libpeci/peci.h | 14 ++++ libpeci/peci_cmds.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 317 insertions(+), 2 deletions(-) diff --git a/libpeci/peci.c b/libpeci/peci.c index 1d97b93..fee87f2 100644 --- a/libpeci/peci.c +++ b/libpeci/peci.c @@ -897,6 +897,81 @@ EPECIStatus peci_RdEndPointConfigMmio_seq( return ret; } +/*------------------------------------------------------------------------- + * This internal function is the common interface for WdEndPointConfig to PCI + *------------------------------------------------------------------------*/ +static EPECIStatus peci_WrEndPointConfigCommon(uint8_t target, + uint8_t u8MsgType, uint8_t u8Seg, + uint8_t u8Bus, uint8_t u8Device, + uint8_t u8Fcn, uint16_t u16Reg, + uint8_t DataLen, + uint32_t DataVal, uint8_t* cc) +{ + int peci_fd = -1; + struct peci_wr_end_pt_cfg_msg cmd; + EPECIStatus ret; + + if (cc == NULL) + { + return PECI_CC_INVALID_REQ; + } + + // Per the PECI spec, the write length must be a byte, word, or dword + if (DataLen != 1 && DataLen != 2 && DataLen != 4) + { + return PECI_CC_INVALID_REQ; + } + + if (peci_Open(&peci_fd) != PECI_CC_SUCCESS) + { + return PECI_CC_DRIVER_ERR; + } + + cmd.addr = target; + cmd.msg_type = u8MsgType; + cmd.params.pci_cfg.seg = u8Seg; + cmd.params.pci_cfg.bus = u8Bus; + cmd.params.pci_cfg.device = u8Device; + cmd.params.pci_cfg.function = u8Fcn; + cmd.params.pci_cfg.reg = u16Reg; + cmd.tx_len = DataLen; + cmd.value = DataVal; + + ret = HW_peci_issue_cmd(PECI_IOC_WR_END_PT_CFG, (char*)&cmd, peci_fd); + *cc = cmd.cc; + + peci_Close(peci_fd); + return ret; +} + +/*------------------------------------------------------------------------- + * This function provides write access to the EP local PCI configuration space + *------------------------------------------------------------------------*/ +EPECIStatus peci_WrEndPointPCIConfigLocal(uint8_t target, uint8_t u8Seg, + uint8_t u8Bus, uint8_t u8Device, + uint8_t u8Fcn, uint16_t u16Reg, + uint8_t DataLen, uint32_t DataVal, + uint8_t* cc) +{ + return peci_WrEndPointConfigCommon(target, PECI_ENDPTCFG_TYPE_LOCAL_PCI, + u8Seg, u8Bus, u8Device, u8Fcn, u16Reg, + DataLen, DataVal, cc); +} + +/*------------------------------------------------------------------------- + * This function provides write access to the EP local PCI configuration space + *------------------------------------------------------------------------*/ +EPECIStatus peci_WrEndPointPCIConfig(uint8_t target, uint8_t u8Seg, + uint8_t u8Bus, uint8_t u8Device, + uint8_t u8Fcn, uint16_t u16Reg, + uint8_t DataLen, uint32_t DataVal, + uint8_t* cc) +{ + return peci_WrEndPointConfigCommon(target, PECI_ENDPTCFG_TYPE_PCI, u8Seg, + u8Bus, u8Device, u8Fcn, u16Reg, DataLen, + DataVal, cc); +} + /*------------------------------------------------------------------------- * This function provides crashdump discovery data over PECI *------------------------------------------------------------------------*/ diff --git a/libpeci/peci.h b/libpeci/peci.h index 05a60bd..ba24d02 100644 --- a/libpeci/peci.h +++ b/libpeci/peci.h @@ -195,6 +195,20 @@ EPECIStatus peci_RdEndPointConfigMmio_seq( uint8_t u8Fcn, uint8_t u8Bar, uint8_t u8AddrType, uint64_t u64Offset, uint8_t u8ReadLen, uint8_t* pMmioData, int peci_fd, uint8_t* cc); +// Provides write access to the EP local PCI Configuration space +EPECIStatus peci_WrEndPointPCIConfigLocal(uint8_t target, uint8_t u8Seg, + uint8_t u8Bus, uint8_t u8Device, + uint8_t u8Fcn, uint16_t u16Reg, + uint8_t DataLen, uint32_t DataVal, + uint8_t* cc); + +// Provides write access to the EP PCI Configuration space +EPECIStatus peci_WrEndPointPCIConfig(uint8_t target, uint8_t u8Seg, + uint8_t u8Bus, uint8_t u8Device, + uint8_t u8Fcn, uint16_t u16Reg, + uint8_t DataLen, uint32_t DataVal, + uint8_t* cc); + // Provides access to the Crashdump Discovery API EPECIStatus peci_CrashDump_Discovery(uint8_t target, uint8_t subopcode, uint8_t param0, uint16_t param1, diff --git a/libpeci/peci_cmds.c b/libpeci/peci_cmds.c index ba37810..9aafe06 100644 --- a/libpeci/peci_cmds.c +++ b/libpeci/peci_cmds.c @@ -22,6 +22,15 @@ #define ABS(_v_) (((_v_) > 0) ? (_v_) : -(_v_)) #endif +enum peci_cmd_subtype +{ + PECI_CMD_RD_END_PT_CFG_LOCAL_PCI = PECI_CMD_MAX + 1, + PECI_CMD_RD_END_PT_CFG_PCI, + PECI_CMD_RD_END_PT_CFG_MMIO, + PECI_CMD_WR_END_PT_CFG_LOCAL_PCI, + PECI_CMD_WR_END_PT_CFG_PCI, +}; + extern EPECIStatus peci_GetDIB(uint8_t target, uint64_t* dib); void Usage(char* progname) @@ -45,6 +54,15 @@ void Usage(char* progname) "[Reg]>.\n"); printf("\t\t-lw : Local PCI Write for specific hex address .\n"); + printf("\t\t-e : Endpoint Local PCI Config Read ." + "\n"); + printf("\t\t-ew : Endpoint Local PCI Config Write .\n"); + printf("\t\t-f : Endpoint PCI Config Read .\n"); + printf("\t\t-fw : Endpoint PCI Config Write ." + "\n"); + printf("\t\t-g : Endpoint MMIO Read ." + "\n"); printf("\n"); } @@ -57,10 +75,14 @@ int main(int argc, char* argv[]) uint8_t address = 0x30; // use default address of 48d uint8_t u8Size = 4; // default to a DWORD uint32_t u32PciReadVal = 0; + uint8_t u8Seg = 0; + uint8_t u8Bar = 0; + uint8_t u8AddrType = 0; uint8_t u8PciBus = 0; uint8_t u8PciDev = 0; uint8_t u8PciFunc = 0; uint16_t u16PciReg = 0; + uint64_t u64Offset = 0; uint32_t u32PciWriteVal = 0; uint8_t u8PkgIndex = 0; uint16_t u16PkgParam = 0; @@ -77,7 +99,7 @@ int main(int argc, char* argv[]) // // Parse arguments. // - while (-1 != (c = getopt(argc, argv, "a:s:nbtdp::c::m::l::"))) + while (-1 != (c = getopt(argc, argv, "a:s:nbtdp::c::m::l::e::f::g"))) { switch (c) { @@ -136,6 +158,25 @@ int main(int argc, char* argv[]) u8Cmd = PECI_CMD_WR_PCI_CFG_LOCAL; break; + case 'e': + cnt++; + u8Cmd = PECI_CMD_RD_END_PT_CFG_LOCAL_PCI; + if (optarg != NULL && optarg[0] == 'w') + u8Cmd = PECI_CMD_WR_END_PT_CFG_LOCAL_PCI; + break; + + case 'f': + cnt++; + u8Cmd = PECI_CMD_RD_END_PT_CFG_PCI; + if (optarg != NULL && optarg[0] == 'w') + u8Cmd = PECI_CMD_WR_END_PT_CFG_PCI; + break; + + case 'g': + cnt++; + u8Cmd = PECI_CMD_RD_END_PT_CFG_MMIO; + break; + default: printf("ERROR: Unrecognized option \"-%c\".\n", optopt); goto ErrorExit; @@ -357,10 +398,195 @@ int main(int argc, char* argv[]) : printf("Failed or not supported.\n"); break; + case PECI_CMD_RD_END_PT_CFG_LOCAL_PCI: + u8Index = argc; + switch (argc - optind) + { + case 5: + u16PciReg = strtoul(argv[--u8Index], NULL, 16); + u8PciFunc = strtoul(argv[--u8Index], NULL, 16); + u8PciDev = strtoul(argv[--u8Index], NULL, 16); + u8PciBus = strtoul(argv[--u8Index], NULL, 16); + u8Seg = strtoul(argv[--u8Index], NULL, 16); + break; + + default: + printf("ERROR: Unsupported arguments for Endpoint Local" + "PCI Read\n"); + goto ErrorExit; + } + + ret = peci_RdEndPointConfigPciLocal( + address, u8Seg, u8PciBus, u8PciDev, u8PciFunc, u16PciReg, + u8Size, (uint8_t*)&u32PciReadVal, &cc); + if (showCc) + { + printf("Endpoint Local PCI Read cc:0x%x\n", cc); + } + printf("Seg:%02x %02x:%02x:%02x " + "Reg %02x: 0x%0*x\n", + u8Seg, u8PciBus, u8PciDev, u8PciFunc, u16PciReg, u8Size * 2, + u32PciReadVal); + if (0 != ret) + { + printf("ERROR: Endpoint Local PCI Read failed or is " + "not supported.\n"); + break; + } + break; + + case PECI_CMD_WR_END_PT_CFG_LOCAL_PCI: + u8Index = argc; + switch (argc - optind) + { + case 6: + u32PciWriteVal = strtoul(argv[--u8Index], NULL, 16); + u16PciReg = strtoul(argv[--u8Index], NULL, 16); + u8PciFunc = strtoul(argv[--u8Index], NULL, 16); + u8PciDev = strtoul(argv[--u8Index], NULL, 16); + u8PciBus = strtoul(argv[--u8Index], NULL, 16); + u8Seg = strtoul(argv[--u8Index], NULL, 16); + break; + + default: + printf("ERROR: Unsupported arguments for Endpoint Local " + "PCI Write\n"); + goto ErrorExit; + } + + ret = peci_WrEndPointPCIConfigLocal(address, u8Seg, u8PciBus, + u8PciDev, u8PciFunc, u16PciReg, + u8Size, u32PciWriteVal, &cc); + if (showCc) + { + printf("Endpoint Local PCI Write cc:0x%x\n", cc); + } + printf("Seg:%02x %02x:%02x:%02x Reg %02x: 0x%0*x\n", u8Seg, + u8PciBus, u8PciDev, u8PciFunc, u16PciReg, u8Size * 2, + u32PciWriteVal); + if (0 != ret) + { + printf("ERROR: Endpoint Local PCI Write failed " + "or is not supported.\n"); + break; + } + break; + + case PECI_CMD_RD_END_PT_CFG_PCI: + u8Index = argc; + switch (argc - optind) + { + case 5: + u16PciReg = strtoul(argv[--u8Index], NULL, 16); + u8PciFunc = strtoul(argv[--u8Index], NULL, 16); + u8PciDev = strtoul(argv[--u8Index], NULL, 16); + u8PciBus = strtoul(argv[--u8Index], NULL, 16); + u8Seg = strtoul(argv[--u8Index], NULL, 16); + break; + + default: + printf("ERROR: Unsupported arguments for Endpoint PCI Read" + "\n"); + goto ErrorExit; + } + + ret = peci_RdEndPointConfigPci(address, u8Seg, u8PciBus, u8PciDev, + u8PciFunc, u16PciReg, u8Size, + (uint8_t*)&u32PciReadVal, &cc); + if (showCc) + { + printf("Endpoint PCI Read cc:0x%x\n", cc); + } + printf("Seg:%02x %02x:%02x:%02x Reg %02x: 0x%0*x\n", u8Seg, + u8PciBus, u8PciDev, u8PciFunc, u16PciReg, u8Size * 2, + u32PciReadVal); + if (0 != ret) + { + printf("ERROR: Endpoint PCI Read failed or is not supported." + "\n"); + break; + } + break; + + case PECI_CMD_WR_END_PT_CFG_PCI: + u8Index = argc; + switch (argc - optind) + { + case 6: + u32PciWriteVal = strtoul(argv[--u8Index], NULL, 16); + u16PciReg = strtoul(argv[--u8Index], NULL, 16); + u8PciFunc = strtoul(argv[--u8Index], NULL, 16); + u8PciDev = strtoul(argv[--u8Index], NULL, 16); + u8PciBus = strtoul(argv[--u8Index], NULL, 16); + u8Seg = strtoul(argv[--u8Index], NULL, 16); + break; + + default: + printf("ERROR: Unsupported arguments for Endpoint PCI Write" + "\n"); + goto ErrorExit; + } + + ret = peci_WrEndPointPCIConfig(address, u8Seg, u8PciBus, u8PciDev, + u8PciFunc, u16PciReg, u8Size, + u32PciWriteVal, &cc); + if (showCc) + { + printf("Endpoint PCI Write cc:0x%x\n", cc); + } + printf("Seg:%02x %02x:%02x:%02x Reg %02x: 0x%0*x\n", u8Seg, + u8PciBus, u8PciDev, u8PciFunc, u16PciReg, u8Size * 2, + u32PciWriteVal); + if (0 != ret) + { + printf("ERROR: Endpoint PCI Write failed or is not supported." + "\n"); + break; + } + break; + + case PECI_CMD_RD_END_PT_CFG_MMIO: + u8Index = argc; + switch (argc - optind) + { + case 7: + u64Offset = strtoul(argv[--u8Index], NULL, 16); + u8PciFunc = strtoul(argv[--u8Index], NULL, 16); + u8PciDev = strtoul(argv[--u8Index], NULL, 16); + u8PciBus = strtoul(argv[--u8Index], NULL, 16); + u8Seg = strtoul(argv[--u8Index], NULL, 16); + u8Bar = strtoul(argv[--u8Index], NULL, 16); + u8AddrType = strtoul(argv[--u8Index], NULL, 16); + break; + + default: + printf("ERROR: Unsupported arguments for Endpoint MMIO Read" + "\n"); + goto ErrorExit; + } + + ret = peci_RdEndPointConfigMmio( + address, u8Seg, u8PciBus, u8PciDev, u8PciFunc, u8Bar, + u8AddrType, u64Offset, u8Size, (uint8_t*)&u32PciReadVal, &cc); + if (showCc) + { + printf("Endpoint MMIO Read cc:0x%x\n", cc); + } + printf("Seg:%02x %02x:%02x:%02x AType:%02x Bar:%02x " + "Offset:0x%" PRIx64 " Data:0x%0*x\n", + u8Seg, u8PciBus, u8PciDev, u8PciFunc, u8AddrType, u8Bar, + u64Offset, u8Size * 2, u32PciReadVal); + if (0 != ret) + { + printf("ERROR: Endpoint MMIO Read failed or is not supported." + "\n"); + break; + } + break; + default: printf("ERROR: Unrecognized command\n"); goto ErrorExit; - break; } return 0; -- cgit v1.2.3