connect - add comments and add input verification
devices - add comments and add input verification devtree - add comments and add input verification dh - add comments, add input verification, add support for "-d" disconnect - add comments and add input verification drivers - add comments drvcfg - add comment drvdiag - add comments, add input verification, and fix language use openinfo - add comments and add input verification reconnect - add comment unload - add input verification. main library files: add comments, #define protection, and more output to the user. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11434 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
Main file for DrvDiag shell Driver1 function.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
@ -19,13 +19,27 @@ STATIC CONST EFI_GUID *DiagGuidList[] = {&gEfiDriverDiagnosticsProtocolGuid, &gE
|
||||
// We need 1 more item on the list...
|
||||
//
|
||||
typedef enum {
|
||||
TEST_MODE_STANDARD = EfiDriverDiagnosticTypeStandard,
|
||||
TEST_MODE_EXTENDED = EfiDriverDiagnosticTypeExtended,
|
||||
TEST_MODE_MANUFACTURING = EfiDriverDiagnosticTypeManufacturing,
|
||||
TEST_MODE_LIST,
|
||||
TEST_MODE_MAX
|
||||
TestModeStandard = EfiDriverDiagnosticTypeStandard,
|
||||
TestModeExtended = EfiDriverDiagnosticTypeExtended,
|
||||
TestModeManufacturing = EfiDriverDiagnosticTypeManufacturing,
|
||||
TestModeList,
|
||||
TestModeMax
|
||||
} DRV_DIAG_TEST_MODE;
|
||||
|
||||
/**
|
||||
Do the diagnostics call for some set of handles.
|
||||
|
||||
@param[in] Mode The type of diagnostic test to run.
|
||||
@param[in] Lang The language code to use.
|
||||
@param[in] AllChilds Should the test be on all children.
|
||||
@param[in] DriverHandle The driver handle to test with.
|
||||
@param[in] ControllerHandle The specific controller handle to test.
|
||||
@param[in] ChildHandle The specific child handle to test.
|
||||
|
||||
@retval EFI_SUCCESS The operation was successful.
|
||||
@retval EFI_INVALID_PARAMETER A parameter had an invalid value.
|
||||
@retval EFI_NOT_FOUND No diagnostic handle could be found.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DoDiagnostics (
|
||||
@ -56,13 +70,11 @@ DoDiagnostics (
|
||||
CHAR16 *OutBuffer;
|
||||
UINTN HandleIndex1;
|
||||
UINTN HandleIndex2;
|
||||
CHAR8 *Language;
|
||||
CHAR8 *TempChar;
|
||||
BOOLEAN Found;
|
||||
|
||||
if ((ChildHandle != NULL && AllChilds) || (Mode >= TEST_MODE_MAX)){
|
||||
return (EFI_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
if (Lang == NULL || AsciiStrLen(Lang) < 3) {
|
||||
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"-l <value>");
|
||||
if ((ChildHandle != NULL && AllChilds) || (Mode >= TestModeMax)){
|
||||
return (EFI_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
@ -73,6 +85,7 @@ DoDiagnostics (
|
||||
DriverHandleList = NULL;
|
||||
ControllerHandleList = NULL;
|
||||
ChildHandleList = NULL;
|
||||
Language = NULL;
|
||||
OutBuffer = NULL;
|
||||
ErrorType = NULL;
|
||||
DriverHandleListCount = 0;
|
||||
@ -87,7 +100,8 @@ DoDiagnostics (
|
||||
} else {
|
||||
DriverHandleList = GetHandleListByProtocolList(DiagGuidList);
|
||||
if (DriverHandleList == NULL) {
|
||||
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DRVCFG_NONE), gShellDriver1HiiHandle);
|
||||
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROTOCOL_NF), gShellDriver1HiiHandle, L"gEfiDriverDiagnosticsProtocolGuid", &gEfiDriverDiagnosticsProtocolGuid);
|
||||
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROTOCOL_NF), gShellDriver1HiiHandle, L"gEfiDriverDiagnostics2ProtocolGuid", &gEfiDriverDiagnostics2ProtocolGuid);
|
||||
return (EFI_NOT_FOUND);
|
||||
}
|
||||
for (Walker = DriverHandleList ; Walker != NULL && *Walker != NULL ; DriverHandleListCount++, Walker++);
|
||||
@ -116,132 +130,186 @@ DoDiagnostics (
|
||||
ChildHandleList = NULL;
|
||||
}
|
||||
|
||||
if (Mode == TestModeList) {
|
||||
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DRVDIAG_HEADER), gShellDriver1HiiHandle);
|
||||
}
|
||||
for (DriverHandleListLoop = 0
|
||||
; DriverHandleListLoop < DriverHandleListCount
|
||||
; DriverHandleListLoop++
|
||||
){
|
||||
if (Mode == TestModeList) {
|
||||
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DRVDIAG_DRIVER_HEADER), gShellDriver1HiiHandle, ConvertHandleToHandleIndex(DriverHandleList[DriverHandleListLoop]));
|
||||
}
|
||||
if (ControllerHandle == NULL) {
|
||||
PARSE_HANDLE_DATABASE_DEVICES(DriverHandleList[DriverHandleListLoop], &ControllerHandleListCount, &ControllerHandleList);
|
||||
}
|
||||
for (ControllerHandleListLoop = 0
|
||||
; ControllerHandleListLoop < ControllerHandleListCount
|
||||
; ControllerHandleListLoop++
|
||||
){
|
||||
if (AllChilds) {
|
||||
ASSERT(ChildHandleList == NULL);
|
||||
PARSE_HANDLE_DATABASE_MANAGED_CHILDREN(
|
||||
DriverHandleList[DriverHandleListLoop],
|
||||
ControllerHandleList[ControllerHandleListLoop],
|
||||
&ChildHandleListCount,
|
||||
&ChildHandleList);
|
||||
}
|
||||
if (ControllerHandleListCount == 0) {
|
||||
if (Mode == TestModeList) {
|
||||
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DRVDIAG_DRIVER_NO_HANDLES), gShellDriver1HiiHandle);
|
||||
}
|
||||
for (ChildHandleListLoop = 0
|
||||
; (ChildHandleListLoop < ChildHandleListCount || ChildHandleList == NULL)
|
||||
; ChildHandleListLoop++
|
||||
} else {
|
||||
if (Mode == TestModeList) {
|
||||
ShellPrintEx(-1, -1, L"\r\n");
|
||||
}
|
||||
for (ControllerHandleListLoop = 0
|
||||
; ControllerHandleListLoop < ControllerHandleListCount
|
||||
; ControllerHandleListLoop++
|
||||
){
|
||||
if (Mode != TEST_MODE_LIST) {
|
||||
if (Lang[2] == '-') {
|
||||
//
|
||||
// Get the protocol pointer and call the function
|
||||
//
|
||||
Status = gBS->OpenProtocol(
|
||||
DriverHandleList[DriverHandleListLoop],
|
||||
&gEfiDriverDiagnostics2ProtocolGuid,
|
||||
(VOID**)&DriverDiagnostics2,
|
||||
gImageHandle,
|
||||
if (AllChilds) {
|
||||
ASSERT(ChildHandleList == NULL);
|
||||
PARSE_HANDLE_DATABASE_MANAGED_CHILDREN(
|
||||
DriverHandleList[DriverHandleListLoop],
|
||||
ControllerHandleList[ControllerHandleListLoop],
|
||||
&ChildHandleListCount,
|
||||
&ChildHandleList);
|
||||
}
|
||||
for (ChildHandleListLoop = 0
|
||||
; (ChildHandleListLoop < ChildHandleListCount || ChildHandleList == NULL)
|
||||
; ChildHandleListLoop++
|
||||
){
|
||||
Found = FALSE;
|
||||
if (Mode != TestModeList) {
|
||||
if (Lang == NULL || Lang[2] == '-') {
|
||||
//
|
||||
// Get the protocol pointer and call the function
|
||||
//
|
||||
Status = gBS->OpenProtocol(
|
||||
DriverHandleList[DriverHandleListLoop],
|
||||
&gEfiDriverDiagnostics2ProtocolGuid,
|
||||
(VOID**)&DriverDiagnostics2,
|
||||
gImageHandle,
|
||||
NULL,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
if (Lang == NULL) {
|
||||
Language = AllocateZeroPool(AsciiStrSize(DriverDiagnostics2->SupportedLanguages));
|
||||
if (Language == NULL) {
|
||||
return (EFI_OUT_OF_RESOURCES);
|
||||
}
|
||||
AsciiStrCpy(Language, DriverDiagnostics2->SupportedLanguages);
|
||||
TempChar = AsciiStrStr(Language, ";");
|
||||
if (TempChar != NULL){
|
||||
*TempChar = CHAR_NULL;
|
||||
}
|
||||
} else {
|
||||
Language = AllocateZeroPool(AsciiStrSize(Lang));
|
||||
if (Language == NULL) {
|
||||
return (EFI_OUT_OF_RESOURCES);
|
||||
}
|
||||
AsciiStrCpy(Language, Lang);
|
||||
}
|
||||
Found = TRUE;
|
||||
Status = DriverDiagnostics2->RunDiagnostics(
|
||||
DriverDiagnostics2,
|
||||
ControllerHandleList[ControllerHandleListLoop],
|
||||
ChildHandleList == NULL?NULL:ChildHandleList[ChildHandleListLoop],
|
||||
(EFI_DRIVER_DIAGNOSTIC_TYPE)Mode,
|
||||
Language,
|
||||
&ErrorType,
|
||||
&OutBufferSize,
|
||||
&OutBuffer);
|
||||
FreePool(Language);
|
||||
}
|
||||
}
|
||||
if (Found == FALSE && (Lang == NULL||(Lang!=NULL&&Lang[2]!='-'))){
|
||||
Status = gBS->OpenProtocol(
|
||||
DriverHandleList[DriverHandleListLoop],
|
||||
&gEfiDriverDiagnosticsProtocolGuid,
|
||||
(VOID**)&DriverDiagnostics,
|
||||
gImageHandle,
|
||||
NULL,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
if (Lang == NULL) {
|
||||
Language = AllocateZeroPool(AsciiStrSize(DriverDiagnostics2->SupportedLanguages));
|
||||
if (Language == NULL) {
|
||||
return (EFI_OUT_OF_RESOURCES);
|
||||
}
|
||||
AsciiStrCpy(Language, DriverDiagnostics2->SupportedLanguages);
|
||||
TempChar = AsciiStrStr(Language, ";");
|
||||
if (TempChar != NULL){
|
||||
*TempChar = CHAR_NULL;
|
||||
}
|
||||
} else {
|
||||
Language = AllocateZeroPool(AsciiStrSize(Lang));
|
||||
if (Language == NULL) {
|
||||
return (EFI_OUT_OF_RESOURCES);
|
||||
}
|
||||
AsciiStrCpy(Language, Lang);
|
||||
}
|
||||
Status = DriverDiagnostics->RunDiagnostics(
|
||||
DriverDiagnostics,
|
||||
ControllerHandleList[ControllerHandleListLoop],
|
||||
ChildHandleList == NULL?NULL:ChildHandleList[ChildHandleListLoop],
|
||||
(EFI_DRIVER_DIAGNOSTIC_TYPE)Mode,
|
||||
Language,
|
||||
&ErrorType,
|
||||
&OutBufferSize,
|
||||
&OutBuffer);
|
||||
FreePool(Language);
|
||||
}
|
||||
}
|
||||
if (EFI_ERROR(Status)) {
|
||||
Status2 = Status;
|
||||
}
|
||||
HandleIndex1 = ConvertHandleToHandleIndex(DriverHandleList[DriverHandleListLoop]);
|
||||
HandleIndex2 = ConvertHandleToHandleIndex(ControllerHandleList[ControllerHandleListLoop]);
|
||||
ShellPrintHiiEx(
|
||||
-1,
|
||||
-1,
|
||||
NULL,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
Status = DriverDiagnostics2->RunDiagnostics(
|
||||
DriverDiagnostics2,
|
||||
ControllerHandleList[ControllerHandleListLoop],
|
||||
ChildHandleList == NULL?NULL:ChildHandleList[ChildHandleListLoop],
|
||||
(EFI_DRIVER_DIAGNOSTIC_TYPE)Mode,
|
||||
(CHAR8*)Lang,
|
||||
&ErrorType,
|
||||
&OutBufferSize,
|
||||
&OutBuffer);
|
||||
STRING_TOKEN (STR_3P_RESULT),
|
||||
gShellDriver1HiiHandle,
|
||||
L"DrvDiag",
|
||||
HandleIndex1,
|
||||
HandleIndex2,
|
||||
ChildHandleList == NULL?0:ConvertHandleToHandleIndex(ChildHandleList[ChildHandleListLoop]),
|
||||
Status);
|
||||
if (OutBuffer!=NULL) {
|
||||
FreePool(OutBuffer);
|
||||
OutBuffer = NULL;
|
||||
}
|
||||
if (ErrorType!=NULL) {
|
||||
FreePool(ErrorType);
|
||||
ErrorType = NULL;
|
||||
}
|
||||
} else {
|
||||
Status = gBS->OpenProtocol(
|
||||
DriverHandleList[DriverHandleListLoop],
|
||||
&gEfiDriverDiagnosticsProtocolGuid,
|
||||
(VOID**)&DriverDiagnostics,
|
||||
gImageHandle,
|
||||
HandleIndex1 = ConvertHandleToHandleIndex(DriverHandleList[DriverHandleListLoop]);
|
||||
HandleIndex2 = ConvertHandleToHandleIndex(ControllerHandleList[ControllerHandleListLoop]);
|
||||
//
|
||||
// Print out the information that this set can be tested
|
||||
//
|
||||
ShellPrintHiiEx(
|
||||
-1,
|
||||
-1,
|
||||
NULL,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
Status = DriverDiagnostics->RunDiagnostics(
|
||||
DriverDiagnostics,
|
||||
ControllerHandleList[ControllerHandleListLoop],
|
||||
ChildHandleList == NULL?NULL:ChildHandleList[ChildHandleListLoop],
|
||||
(EFI_DRIVER_DIAGNOSTIC_TYPE)Mode,
|
||||
(CHAR8*)Lang,
|
||||
&ErrorType,
|
||||
&OutBufferSize,
|
||||
&OutBuffer);
|
||||
}
|
||||
STRING_TOKEN (STR_DRV_DIAG_ITEM_LINE),
|
||||
gShellDriver1HiiHandle,
|
||||
HandleIndex1,
|
||||
HandleIndex2,
|
||||
ChildHandleList == NULL?0:ConvertHandleToHandleIndex(ChildHandleList[ChildHandleListLoop])
|
||||
);
|
||||
}
|
||||
if (EFI_ERROR(Status)) {
|
||||
Status2 = Status;
|
||||
}
|
||||
HandleIndex1 = ConvertHandleToHandleIndex(DriverHandleList[DriverHandleListLoop]);
|
||||
HandleIndex2 = ConvertHandleToHandleIndex(ControllerHandleList[ControllerHandleListLoop]);
|
||||
ShellPrintHiiEx(
|
||||
-1,
|
||||
-1,
|
||||
NULL,
|
||||
STRING_TOKEN (STR_3P_RESULT),
|
||||
gShellDriver1HiiHandle,
|
||||
L"DrvDiag",
|
||||
HandleIndex1,
|
||||
HandleIndex2,
|
||||
ChildHandleList == NULL?0:ConvertHandleToHandleIndex(ChildHandleList[ChildHandleListLoop]),
|
||||
Status);
|
||||
if (OutBuffer!=NULL) {
|
||||
FreePool(OutBuffer);
|
||||
OutBuffer = NULL;
|
||||
}
|
||||
if (ErrorType!=NULL) {
|
||||
FreePool(ErrorType);
|
||||
ErrorType = NULL;
|
||||
}
|
||||
} else {
|
||||
HandleIndex1 = ConvertHandleToHandleIndex(DriverHandleList[DriverHandleListLoop]);
|
||||
HandleIndex2 = ConvertHandleToHandleIndex(ControllerHandleList[ControllerHandleListLoop]);
|
||||
//
|
||||
// Print out the information that this set can be tested
|
||||
//
|
||||
ShellPrintHiiEx(
|
||||
-1,
|
||||
-1,
|
||||
NULL,
|
||||
STRING_TOKEN (STR_DRV_DIAG_ITEM_LINE),
|
||||
gShellDriver1HiiHandle,
|
||||
HandleIndex1,
|
||||
HandleIndex2,
|
||||
ChildHandleList == NULL?0:ConvertHandleToHandleIndex(ChildHandleList[ChildHandleListLoop])
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// If we are doing a single pass with NULL child jump out after a single loop
|
||||
//
|
||||
if (ChildHandleList == NULL) {
|
||||
break;
|
||||
//
|
||||
// If we are doing a single pass with NULL child jump out after a single loop
|
||||
//
|
||||
if (ChildHandleList == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (AllChilds) {
|
||||
SHELL_FREE_NON_NULL(ChildHandleList);
|
||||
ChildHandleList = NULL;
|
||||
ChildHandleListCount = 0;
|
||||
}
|
||||
}
|
||||
if (AllChilds) {
|
||||
SHELL_FREE_NON_NULL(ChildHandleList);
|
||||
ChildHandleList = NULL;
|
||||
ChildHandleListCount = 0;
|
||||
if (ControllerHandle == NULL) {
|
||||
SHELL_FREE_NON_NULL(ControllerHandleList);
|
||||
ControllerHandleList = NULL;
|
||||
ControllerHandleListCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ControllerHandle == NULL) {
|
||||
SHELL_FREE_NON_NULL(ControllerHandleList);
|
||||
ControllerHandleList = NULL;
|
||||
ControllerHandleListCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (DriverHandleList != NULL) {
|
||||
@ -266,6 +334,12 @@ STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
|
||||
{NULL, TypeMax}
|
||||
};
|
||||
|
||||
/**
|
||||
Function for 'drvdiag' command.
|
||||
|
||||
@param[in] ImageHandle Handle to the Image (NULL if Internal).
|
||||
@param[in] SystemTable Pointer to the System Table (NULL if Internal).
|
||||
**/
|
||||
SHELL_STATUS
|
||||
EFIAPI
|
||||
ShellCommandRunDrvDiag (
|
||||
@ -286,9 +360,10 @@ ShellCommandRunDrvDiag (
|
||||
EFI_HANDLE Handle1;
|
||||
EFI_HANDLE Handle2;
|
||||
EFI_HANDLE Handle3;
|
||||
UINT64 Intermediate;
|
||||
|
||||
ShellStatus = SHELL_SUCCESS;
|
||||
Mode = TEST_MODE_MAX;
|
||||
Mode = TestModeMax;
|
||||
Language = NULL;
|
||||
|
||||
//
|
||||
@ -334,11 +409,11 @@ ShellCommandRunDrvDiag (
|
||||
// Run the apropriate test
|
||||
//
|
||||
if (ShellCommandLineGetFlag(Package, L"-s")) {
|
||||
Mode = TEST_MODE_STANDARD;
|
||||
Mode = TestModeStandard;
|
||||
} else if (ShellCommandLineGetFlag(Package, L"-e")) {
|
||||
Mode = TEST_MODE_EXTENDED;
|
||||
Mode = TestModeExtended;
|
||||
} else if (ShellCommandLineGetFlag(Package, L"-m")) {
|
||||
Mode = TEST_MODE_MANUFACTURING;
|
||||
Mode = TestModeManufacturing;
|
||||
} else {
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
@ -346,21 +421,18 @@ ShellCommandRunDrvDiag (
|
||||
//
|
||||
// Do a listing of what's available to test
|
||||
//
|
||||
Mode = TEST_MODE_LIST;
|
||||
Mode = TestModeList;
|
||||
}
|
||||
|
||||
Lang = ShellCommandLineGetValue(Package, L"-l");
|
||||
if (Lang != NULL) {
|
||||
Language = AllocateZeroPool(StrSize(Lang));
|
||||
AsciiSPrint(Language, StrSize(Lang), "%S", Lang);
|
||||
} else if (!ShellCommandLineGetFlag(Package, L"-l")){
|
||||
Language = AllocateZeroPool(10);
|
||||
AsciiSPrint(Language, 10, "en-us");
|
||||
} else {
|
||||
if (ShellCommandLineGetFlag(Package, L"-l") && Lang == NULL) {
|
||||
ASSERT(Language == NULL);
|
||||
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"-l");
|
||||
ShellCommandLineFreeVarList (Package);
|
||||
return (SHELL_INVALID_PARAMETER);
|
||||
} else if (Lang != NULL) {
|
||||
Language = AllocateZeroPool(StrSize(Lang));
|
||||
AsciiSPrint(Language, StrSize(Lang), "%S", Lang);
|
||||
}
|
||||
|
||||
DriverHandleStr = ShellCommandLineGetRawValue(Package, 1);
|
||||
@ -370,17 +442,20 @@ ShellCommandRunDrvDiag (
|
||||
if (DriverHandleStr == NULL) {
|
||||
Handle1 = NULL;
|
||||
} else {
|
||||
Handle1 = ConvertHandleIndexToHandle(StrHexToUintn(DriverHandleStr ));
|
||||
ShellConvertStringToUint64(DriverHandleStr, &Intermediate, TRUE, FALSE);
|
||||
Handle1 = ConvertHandleIndexToHandle((UINTN)Intermediate);
|
||||
}
|
||||
if (ControllerHandleStr == NULL) {
|
||||
Handle2 = NULL;
|
||||
} else {
|
||||
Handle2 = ConvertHandleIndexToHandle(StrHexToUintn(ControllerHandleStr));
|
||||
ShellConvertStringToUint64(ControllerHandleStr, &Intermediate, TRUE, FALSE);
|
||||
Handle2 = ConvertHandleIndexToHandle((UINTN)Intermediate);
|
||||
}
|
||||
if (ChildHandleStr == NULL) {
|
||||
Handle3 = NULL;
|
||||
} else {
|
||||
Handle3 = ConvertHandleIndexToHandle(StrHexToUintn(ChildHandleStr ));
|
||||
ShellConvertStringToUint64(ChildHandleStr, &Intermediate, TRUE, FALSE);
|
||||
Handle3 = ConvertHandleIndexToHandle((UINTN)Intermediate);
|
||||
}
|
||||
|
||||
Status = DoDiagnostics (
|
||||
|
Reference in New Issue
Block a user