sw_apps:zynqmp_fsbl: Added support for SD1 and SD1 with level shifter bootmodes
This patch adds support for SD1 and SD1 with level shifter bootmodes in FSBL Signed-off-by: Sarat Chand Savitala <saratcha@xilinx.com> Acked-by: Krishna Chaitanya Patakamuri <kpataka@xilinx.com>
This commit is contained in:
parent
5ed1c08082
commit
f6f21678a4
10 changed files with 93 additions and 37 deletions
|
@ -534,10 +534,14 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Definition for SD to be included
|
* Definitions for SD to be included
|
||||||
*/
|
*/
|
||||||
#if (!defined(FSBL_SD_EXCLUDE) && defined( XPAR_XSDPS_0_DEVICE_ID))
|
#if (!defined(FSBL_SD_EXCLUDE) && defined(XPAR_XSDPS_0_DEVICE_ID))
|
||||||
#define XFSBL_SD
|
#define XFSBL_SD_0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (!defined(FSBL_SD_EXCLUDE) && defined(XPAR_XSDPS_1_DEVICE_ID))
|
||||||
|
#define XFSBL_SD_1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -451,8 +451,10 @@ static u32 XFsbl_PrimaryBootDeviceInit(XFsblPs * FsblInstancePtr)
|
||||||
if ( (BootMode == XFSBL_QSPI24_BOOT_MODE) ||
|
if ( (BootMode == XFSBL_QSPI24_BOOT_MODE) ||
|
||||||
(BootMode == XFSBL_QSPI32_BOOT_MODE) ||
|
(BootMode == XFSBL_QSPI32_BOOT_MODE) ||
|
||||||
(BootMode == XFSBL_NAND_BOOT_MODE) ||
|
(BootMode == XFSBL_NAND_BOOT_MODE) ||
|
||||||
(BootMode == XFSBL_SD_BOOT_MODE) ||
|
(BootMode == XFSBL_SD0_BOOT_MODE) ||
|
||||||
(BootMode == XFSBL_EMMC_BOOT_MODE) ) {
|
(BootMode == XFSBL_EMMC_BOOT_MODE) ||
|
||||||
|
(BootMode == XFSBL_SD1_BOOT_MODE) ||
|
||||||
|
(BootMode == XFSBL_SD1_LS_BOOT_MODE)) {
|
||||||
/**
|
/**
|
||||||
* Initialize the WDT and CSU drivers
|
* Initialize the WDT and CSU drivers
|
||||||
*/
|
*/
|
||||||
|
@ -548,11 +550,16 @@ static u32 XFsbl_PrimaryBootDeviceInit(XFsblPs * FsblInstancePtr)
|
||||||
#endif
|
#endif
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case XFSBL_SD_BOOT_MODE:
|
case XFSBL_SD0_BOOT_MODE:
|
||||||
case XFSBL_EMMC_BOOT_MODE:
|
case XFSBL_EMMC_BOOT_MODE:
|
||||||
{
|
{
|
||||||
XFsbl_Printf(DEBUG_GENERAL,"SD/eMMC Boot Mode \n\r");
|
if (BootMode == XFSBL_SD0_BOOT_MODE) {
|
||||||
#ifdef XFSBL_SD
|
XFsbl_Printf(DEBUG_GENERAL,"SD0 Boot Mode \n\r");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
XFsbl_Printf(DEBUG_GENERAL,"eMMC Boot Mode \n\r");
|
||||||
|
}
|
||||||
|
#ifdef XFSBL_SD_0
|
||||||
/**
|
/**
|
||||||
* Update the deviceops structure with necessary values
|
* Update the deviceops structure with necessary values
|
||||||
*/
|
*/
|
||||||
|
@ -569,20 +576,31 @@ static u32 XFsbl_PrimaryBootDeviceInit(XFsblPs * FsblInstancePtr)
|
||||||
#endif
|
#endif
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case XFSBL_USB_BOOT_MODE:
|
case XFSBL_SD1_BOOT_MODE:
|
||||||
|
case XFSBL_SD1_LS_BOOT_MODE:
|
||||||
{
|
{
|
||||||
XFsbl_Printf(DEBUG_GENERAL,"USB Boot Mode \n\r");
|
if (BootMode == XFSBL_SD1_BOOT_MODE) {
|
||||||
|
XFsbl_Printf(DEBUG_GENERAL, "SD1 Boot Mode \n\r");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
XFsbl_Printf(DEBUG_GENERAL,
|
||||||
|
"SD1 with level shifter Boot Mode \n\r");
|
||||||
|
}
|
||||||
|
#ifdef XFSBL_SD_1
|
||||||
/**
|
/**
|
||||||
* Update the deviceops structure with necessary values
|
* Update the deviceops structure with necessary values
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
FsblInstancePtr->DeviceOps.DeviceInit = XFsbl_SdInit;
|
||||||
|
FsblInstancePtr->DeviceOps.DeviceCopy = XFsbl_SdCopy;
|
||||||
|
FsblInstancePtr->DeviceOps.DeviceRelease = XFsbl_SdRelease;
|
||||||
|
#else
|
||||||
/**
|
/**
|
||||||
* This bootmode is not supported in this release
|
* This bootmode is not supported in this release
|
||||||
*/
|
*/
|
||||||
XFsbl_Printf(DEBUG_GENERAL,
|
XFsbl_Printf(DEBUG_GENERAL,
|
||||||
"XFSBL_ERROR_UNSUPPORTED_BOOT_MODE\n\r");
|
"XFSBL_ERROR_UNSUPPORTED_BOOT_MODE\n\r");
|
||||||
Status = XFSBL_ERROR_UNSUPPORTED_BOOT_MODE;
|
Status = XFSBL_ERROR_UNSUPPORTED_BOOT_MODE;
|
||||||
|
#endif
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -604,7 +622,7 @@ static u32 XFsbl_PrimaryBootDeviceInit(XFsblPs * FsblInstancePtr)
|
||||||
/**
|
/**
|
||||||
* Initialize the Device Driver
|
* Initialize the Device Driver
|
||||||
*/
|
*/
|
||||||
Status = FsblInstancePtr->DeviceOps.DeviceInit();
|
Status = FsblInstancePtr->DeviceOps.DeviceInit(BootMode);
|
||||||
if (XFSBL_SUCCESS != Status) {
|
if (XFSBL_SUCCESS != Status) {
|
||||||
goto END;
|
goto END;
|
||||||
}
|
}
|
||||||
|
@ -641,8 +659,10 @@ static u32 XFsbl_ValidateHeader(XFsblPs * FsblInstancePtr)
|
||||||
* Calculate the Flash Offset Address
|
* Calculate the Flash Offset Address
|
||||||
* For file system based devices, Flash Offset Address should be 0 always
|
* For file system based devices, Flash Offset Address should be 0 always
|
||||||
*/
|
*/
|
||||||
if ((FsblInstancePtr->PrimaryBootDevice == XFSBL_SD_BOOT_MODE) ||
|
if ((FsblInstancePtr->PrimaryBootDevice == XFSBL_SD0_BOOT_MODE) ||
|
||||||
(FsblInstancePtr->PrimaryBootDevice == XFSBL_EMMC_BOOT_MODE))
|
(FsblInstancePtr->PrimaryBootDevice == XFSBL_EMMC_BOOT_MODE) ||
|
||||||
|
(FsblInstancePtr->PrimaryBootDevice == XFSBL_SD1_BOOT_MODE) ||
|
||||||
|
(FsblInstancePtr->PrimaryBootDevice == XFSBL_SD1_LS_BOOT_MODE))
|
||||||
{
|
{
|
||||||
FsblInstancePtr->ImageOffsetAddress = 0x0U;
|
FsblInstancePtr->ImageOffsetAddress = 0x0U;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -373,8 +373,10 @@ void XFsbl_ErrorLockDown(u32 ErrorStatus)
|
||||||
if ( (BootMode == XFSBL_QSPI24_BOOT_MODE) ||
|
if ( (BootMode == XFSBL_QSPI24_BOOT_MODE) ||
|
||||||
(BootMode == XFSBL_QSPI32_BOOT_MODE) ||
|
(BootMode == XFSBL_QSPI32_BOOT_MODE) ||
|
||||||
(BootMode == XFSBL_NAND_BOOT_MODE) ||
|
(BootMode == XFSBL_NAND_BOOT_MODE) ||
|
||||||
(BootMode == XFSBL_SD_BOOT_MODE) ||
|
(BootMode == XFSBL_SD0_BOOT_MODE) ||
|
||||||
(BootMode == XFSBL_EMMC_BOOT_MODE) )
|
(BootMode == XFSBL_EMMC_BOOT_MODE) ||
|
||||||
|
(BootMode == XFSBL_SD1_BOOT_MODE) ||
|
||||||
|
(BootMode == XFSBL_SD1_LS_BOOT_MODE) )
|
||||||
{
|
{
|
||||||
XFsbl_FallBack();
|
XFsbl_FallBack();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -118,10 +118,11 @@ typedef struct {
|
||||||
#define XFSBL_JTAG_BOOT_MODE (0x0U)
|
#define XFSBL_JTAG_BOOT_MODE (0x0U)
|
||||||
#define XFSBL_QSPI24_BOOT_MODE (0x1U)
|
#define XFSBL_QSPI24_BOOT_MODE (0x1U)
|
||||||
#define XFSBL_QSPI32_BOOT_MODE (0x2U)
|
#define XFSBL_QSPI32_BOOT_MODE (0x2U)
|
||||||
#define XFSBL_SD_BOOT_MODE (0x3U)
|
#define XFSBL_SD0_BOOT_MODE (0x3U)
|
||||||
#define XFSBL_NAND_BOOT_MODE (0x4U)
|
#define XFSBL_NAND_BOOT_MODE (0x4U)
|
||||||
|
#define XFSBL_SD1_BOOT_MODE (0x5U)
|
||||||
#define XFSBL_EMMC_BOOT_MODE (0x6U)
|
#define XFSBL_EMMC_BOOT_MODE (0x6U)
|
||||||
#define XFSBL_USB_BOOT_MODE (0x7U)
|
#define XFSBL_SD1_LS_BOOT_MODE (0xEU)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FSBL stages definition
|
* FSBL stages definition
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
|
|
||||||
/***************************** Include Files *********************************/
|
/***************************** Include Files *********************************/
|
||||||
#include "xfsbl_hw.h"
|
#include "xfsbl_hw.h"
|
||||||
|
#include "xfsbl_main.h"
|
||||||
#include "xil_exception.h"
|
#include "xil_exception.h"
|
||||||
|
|
||||||
/************************** Constant Definitions *****************************/
|
/************************** Constant Definitions *****************************/
|
||||||
|
@ -297,7 +298,8 @@ u32 XFsbl_Htonl(u32 Value1)
|
||||||
* @return None
|
* @return None
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
void XFsbl_MakeSdFileName(char *XFsbl_SdEmmcFileName, u32 MultibootReg)
|
void XFsbl_MakeSdFileName(char *XFsbl_SdEmmcFileName,
|
||||||
|
u32 MultibootReg, u32 DeviceFlags)
|
||||||
{
|
{
|
||||||
|
|
||||||
u32 Index;
|
u32 Index;
|
||||||
|
@ -307,12 +309,26 @@ void XFsbl_MakeSdFileName(char *XFsbl_SdEmmcFileName, u32 MultibootReg)
|
||||||
if (0x0U == MultiBootNum)
|
if (0x0U == MultiBootNum)
|
||||||
{
|
{
|
||||||
/* SD file name is BOOT.BIN when Multiboot register value is 0 */
|
/* SD file name is BOOT.BIN when Multiboot register value is 0 */
|
||||||
(void)XFsbl_Strcpy((char *)XFsbl_SdEmmcFileName, "BOOT.BIN");
|
if ((DeviceFlags == XFSBL_SD0_BOOT_MODE) ||
|
||||||
|
(DeviceFlags == XFSBL_EMMC_BOOT_MODE)) {
|
||||||
|
(void)XFsbl_Strcpy((char *)XFsbl_SdEmmcFileName, "BOOT.BIN");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* For XFSBL_SD1_BOOT_MODE or XFSBL_SD1_LS_BOOT_MODE */
|
||||||
|
(void)XFsbl_Strcpy((char *)XFsbl_SdEmmcFileName, "1:/BOOT.BIN");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* set default SD file name as BOOT0000.BIN */
|
/* set default SD file name as BOOT0000.BIN */
|
||||||
(void)XFsbl_Strcpy((char *)XFsbl_SdEmmcFileName, "BOOT0000.BIN");
|
if ((DeviceFlags == XFSBL_SD0_BOOT_MODE) ||
|
||||||
|
(DeviceFlags == XFSBL_EMMC_BOOT_MODE)) {
|
||||||
|
(void)XFsbl_Strcpy((char *)XFsbl_SdEmmcFileName, "BOOT0000.BIN");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* For XFSBL_SD1_BOOT_MODE or XFSBL_SD1_LS_BOOT_MODE */
|
||||||
|
(void)XFsbl_Strcpy((char *)XFsbl_SdEmmcFileName, "1:/BOOT0000.BIN");
|
||||||
|
}
|
||||||
|
|
||||||
/* Update file name (to BOOTXXXX.BIN) based on Multiboot register value */
|
/* Update file name (to BOOTXXXX.BIN) based on Multiboot register value */
|
||||||
for(Index = XFSBL_BASE_FILE_NAME_LEN - 1;
|
for(Index = XFSBL_BASE_FILE_NAME_LEN - 1;
|
||||||
|
|
|
@ -74,7 +74,8 @@ void *XFsbl_MemCpy(void * DestPtr, const void * SrcPtr, u32 Len);
|
||||||
int XFsbl_MemCmp(const void *Str1Ptr, const void *Str2Ptr, u32 Count);
|
int XFsbl_MemCmp(const void *Str1Ptr, const void *Str2Ptr, u32 Count);
|
||||||
char *XFsbl_Strcpy(char *DestPtr, const char *SrcPtr);
|
char *XFsbl_Strcpy(char *DestPtr, const char *SrcPtr);
|
||||||
char * XFsbl_Strcat(char* Str1Ptr, const char* Str2Ptr);
|
char * XFsbl_Strcat(char* Str1Ptr, const char* Str2Ptr);
|
||||||
void XFsbl_MakeSdFileName(char *XFsbl_SdEmmcFileName, u32 MultibootReg);
|
void XFsbl_MakeSdFileName(char *XFsbl_SdEmmcFileName,
|
||||||
|
u32 MultibootReg, u32 DeviceFlags);
|
||||||
u32 XFsbl_Htonl(u32 Value1);
|
u32 XFsbl_Htonl(u32 Value1);
|
||||||
u32 XFsbl_PowerUpIsland(u32 PwrIslandMask);
|
u32 XFsbl_PowerUpIsland(u32 PwrIslandMask);
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ void XFsbl_RestartWdt();
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 DeviceBaseAddress; /**< Flash device base address */
|
u32 DeviceBaseAddress; /**< Flash device base address */
|
||||||
u32 (*DeviceInit) ();
|
u32 (*DeviceInit) (u32 DeviceFlags);
|
||||||
/**< Function pointer for Device initialization code */
|
/**< Function pointer for Device initialization code */
|
||||||
u32 (*DeviceCopy) (u32 SrcAddress, PTRSIZE DestAddress, u32 Length);
|
u32 (*DeviceCopy) (u32 SrcAddress, PTRSIZE DestAddress, u32 Length);
|
||||||
/**< Function pointer for device copy */
|
/**< Function pointer for device copy */
|
||||||
|
@ -97,8 +97,8 @@ typedef struct {
|
||||||
/**
|
/**
|
||||||
* SD driver functions
|
* SD driver functions
|
||||||
*/
|
*/
|
||||||
#ifdef XFSBL_SD
|
#if (defined(XFSBL_SD_0) || defined(XFSBL_SD_1))
|
||||||
u32 XFsbl_SdInit(void );
|
u32 XFsbl_SdInit(u32 DeviceFlags);
|
||||||
u32 XFsbl_SdCopy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length);
|
u32 XFsbl_SdCopy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length);
|
||||||
u32 XFsbl_SdRelease(void );
|
u32 XFsbl_SdRelease(void );
|
||||||
#endif
|
#endif
|
||||||
|
@ -107,7 +107,7 @@ u32 XFsbl_SdRelease(void );
|
||||||
* NAND driver functions
|
* NAND driver functions
|
||||||
*/
|
*/
|
||||||
#ifdef XFSBL_NAND
|
#ifdef XFSBL_NAND
|
||||||
u32 XFsbl_NandInit(void );
|
u32 XFsbl_NandInit(u32 DeviceFlags);
|
||||||
u32 XFsbl_NandCopy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length);
|
u32 XFsbl_NandCopy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length);
|
||||||
u32 XFsbl_NandRelease(void );
|
u32 XFsbl_NandRelease(void );
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -184,7 +184,7 @@ END:
|
||||||
* @return None
|
* @return None
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
u32 XFsbl_Qspi24Init()
|
u32 XFsbl_Qspi24Init(u32 DeviceFlags)
|
||||||
{
|
{
|
||||||
XQspiPsu_Config *QspiConfig;
|
XQspiPsu_Config *QspiConfig;
|
||||||
u32 Status = XFSBL_SUCCESS;
|
u32 Status = XFSBL_SUCCESS;
|
||||||
|
@ -730,7 +730,7 @@ u32 XFsbl_Qspi24Release()
|
||||||
* @return None
|
* @return None
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
u32 XFsbl_Qspi32Init()
|
u32 XFsbl_Qspi32Init(u32 DeviceFlags)
|
||||||
{
|
{
|
||||||
XQspiPsu_Config *QspiConfig;
|
XQspiPsu_Config *QspiConfig;
|
||||||
u32 Status = XFSBL_SUCCESS;
|
u32 Status = XFSBL_SUCCESS;
|
||||||
|
|
|
@ -183,10 +183,10 @@ extern "C" {
|
||||||
|
|
||||||
/************************** Function Prototypes ******************************/
|
/************************** Function Prototypes ******************************/
|
||||||
|
|
||||||
u32 XFsbl_Qspi24Init(void );
|
u32 XFsbl_Qspi24Init(u32 DeviceFlags);
|
||||||
u32 XFsbl_Qspi24Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length);
|
u32 XFsbl_Qspi24Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length);
|
||||||
u32 XFsbl_Qspi24Release(void );
|
u32 XFsbl_Qspi24Release(void );
|
||||||
u32 XFsbl_Qspi32Init(void );
|
u32 XFsbl_Qspi32Init(u32 DeviceFlags);
|
||||||
u32 XFsbl_Qspi32Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length);
|
u32 XFsbl_Qspi32Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length);
|
||||||
u32 XFsbl_Qspi32Release(void );
|
u32 XFsbl_Qspi32Release(void );
|
||||||
|
|
||||||
|
|
|
@ -51,8 +51,9 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
/***************************** Include Files *********************************/
|
/***************************** Include Files *********************************/
|
||||||
#include "xfsbl_hw.h"
|
#include "xfsbl_hw.h"
|
||||||
|
#include "xfsbl_main.h"
|
||||||
|
|
||||||
#ifdef XFSBL_SD
|
#if (defined(XFSBL_SD_0) || defined(XFSBL_SD_1))
|
||||||
|
|
||||||
#include "xparameters.h"
|
#include "xparameters.h"
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
|
@ -64,7 +65,8 @@
|
||||||
/***************** Macros (Inline Functions) Definitions *********************/
|
/***************** Macros (Inline Functions) Definitions *********************/
|
||||||
|
|
||||||
/************************** Function Prototypes ******************************/
|
/************************** Function Prototypes ******************************/
|
||||||
extern void XFsbl_MakeSdFileName(char *XFsbl_SdEmmcFileName, u32 MultibootReg);
|
extern void XFsbl_MakeSdFileName(char *XFsbl_SdEmmcFileName,
|
||||||
|
u32 MultibootReg, u32 DeviceFlags);
|
||||||
|
|
||||||
|
|
||||||
/************************** Variable Definitions *****************************/
|
/************************** Variable Definitions *****************************/
|
||||||
|
@ -81,14 +83,24 @@ static FATFS fatfs;
|
||||||
* @return None
|
* @return None
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
u32 XFsbl_SdInit(void )
|
u32 XFsbl_SdInit(u32 DeviceFlags)
|
||||||
{
|
{
|
||||||
u32 Status = XFSBL_SUCCESS;
|
u32 Status = XFSBL_SUCCESS;
|
||||||
FRESULT rc;
|
FRESULT rc;
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
char *boot_file = buffer;
|
char *boot_file = buffer;
|
||||||
u32 MultiBootOffset=0U;
|
u32 MultiBootOffset=0U;
|
||||||
TCHAR *path = "0:/"; /* Logical drive number is 0 */
|
TCHAR *path;
|
||||||
|
|
||||||
|
/* Set logical drive number as 0 or 1 based on SD0 or SD1 */
|
||||||
|
if ((DeviceFlags == XFSBL_SD0_BOOT_MODE) ||
|
||||||
|
(DeviceFlags == XFSBL_EMMC_BOOT_MODE)) {
|
||||||
|
path = "0:/";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* For XFSBL_SD1_BOOT_MODE or XFSBL_SD1_LS_BOOT_MODE */
|
||||||
|
path = "1:/";
|
||||||
|
}
|
||||||
|
|
||||||
/* Register volume work area, initialize device */
|
/* Register volume work area, initialize device */
|
||||||
rc = f_mount(&fatfs, path, 0);
|
rc = f_mount(&fatfs, path, 0);
|
||||||
|
@ -108,7 +120,7 @@ u32 XFsbl_SdInit(void )
|
||||||
/**
|
/**
|
||||||
* Create boot image name
|
* Create boot image name
|
||||||
*/
|
*/
|
||||||
XFsbl_MakeSdFileName(boot_file, MultiBootOffset);
|
XFsbl_MakeSdFileName(boot_file, MultiBootOffset, DeviceFlags);
|
||||||
|
|
||||||
rc = f_open(&fil, boot_file, FA_READ);
|
rc = f_open(&fil, boot_file, FA_READ);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue