/** @file
  Main file for Disconnect shell Driver1 function.

  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
  (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
  Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
  SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#include "UefiShellDriver1CommandsLib.h"

STATIC CONST SHELL_PARAM_ITEM  ParamList[] = {
  { L"-r",  TypeFlag },
  { L"-nc", TypeFlag },
  { NULL,   TypeMax  }
};

/**
  Disconnect everything.

  @retval EFI_SUCCESS     The operation was successful.
**/
EFI_STATUS
DisconnectAll (
  VOID
  )
{
  //
  // Stolen from UEFI 2.3 spec (May 2009 version)
  // Pages 171/172
  // Removed gBS local definition
  //

  //
  // Disconnect All Handles Example
  // The following example recusively disconnects all drivers from all
  // controllers in a platform.
  //
  EFI_STATUS  Status;
  //  EFI_BOOT_SERVICES *gBS;
  UINTN       HandleCount;
  EFI_HANDLE  *HandleBuffer;
  UINTN       HandleIndex;

  //
  // Retrieve the list of all handles from the handle database
  //
  Status = gBS->LocateHandleBuffer (
                  AllHandles,
                  NULL,
                  NULL,
                  &HandleCount,
                  &HandleBuffer
                  );
  if (!EFI_ERROR (Status)) {
    for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
      Status = gBS->DisconnectController (
                      HandleBuffer[HandleIndex],
                      NULL,
                      NULL
                      );
    }

    gBS->FreePool (HandleBuffer);
    //
    // end of stealing
    //
  }

  return (EFI_SUCCESS);
}

/** Main function of the 'Disconnect' command.

  @param[in] Package    List of input parameter for the command.
**/
STATIC
SHELL_STATUS
MainCmdDisconnect (
  LIST_ENTRY  *Package
  )
{
  EFI_STATUS    Status;
  SHELL_STATUS  ShellStatus;
  CONST CHAR16  *Param1;
  CONST CHAR16  *Param2;
  CONST CHAR16  *Param3;
  EFI_HANDLE    Handle1;
  EFI_HANDLE    Handle2;
  EFI_HANDLE    Handle3;
  UINT64        Intermediate1;
  UINT64        Intermediate2;
  UINT64        Intermediate3;

  Intermediate1 = 0;
  Intermediate2 = 0;
  Intermediate3 = 0;
  ShellStatus   = SHELL_SUCCESS;
  Status        = EFI_SUCCESS;

  if (ShellCommandLineGetFlag (Package, L"-r")) {
    if (ShellCommandLineGetCount (Package) > 1) {
      ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"disconnect");
      return SHELL_INVALID_PARAMETER;
    } else if (ShellCommandLineGetCount (Package) < 1) {
      ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_TOO_FEW), gShellDriver1HiiHandle, L"disconnect");
      return SHELL_INVALID_PARAMETER;
    } else {
      Status = DisconnectAll ();
      //
      // Reconnect all consoles if -nc is not provided
      //
      if (!ShellCommandLineGetFlag (Package, L"-nc")) {
        ShellConnectFromDevPaths (L"ConInDev");
        ShellConnectFromDevPaths (L"ConOutDev");
        ShellConnectFromDevPaths (L"ErrOutDev");
        ShellConnectFromDevPaths (L"ErrOut");
        ShellConnectFromDevPaths (L"ConIn");
        ShellConnectFromDevPaths (L"ConOut");
      }
    }

    // TODO: note: DisconnectAll can only return success
    if (EFI_ERROR (Status)) {
      return SHELL_NOT_FOUND;
    }

    return SHELL_SUCCESS;
  } else if (ShellCommandLineGetFlag (Package, L"-nc")) {
    ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_TOO_FEW), gShellDriver1HiiHandle, L"disconnect");
    return SHELL_INVALID_PARAMETER;
  }

  if (ShellCommandLineGetCount (Package) > 4) {
    ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"disconnect");
    return SHELL_INVALID_PARAMETER;
  } else if (ShellCommandLineGetCount (Package) < 2) {
    ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_TOO_FEW), gShellDriver1HiiHandle, L"disconnect");
    return SHELL_INVALID_PARAMETER;
  }

  //
  // must have between 1 and 3 handles passed in ...
  //
  Param1 = ShellCommandLineGetRawValue (Package, 1);
  Param2 = ShellCommandLineGetRawValue (Package, 2);
  Param3 = ShellCommandLineGetRawValue (Package, 3);

  if (Param1 && !EFI_ERROR (ShellConvertStringToUint64 (Param1, &Intermediate1, TRUE, FALSE))) {
    Handle1 = ConvertHandleIndexToHandle ((UINTN)Intermediate1);
  } else {
    Handle1 = NULL;
  }

  if (Param2 && !EFI_ERROR (ShellConvertStringToUint64 (Param2, &Intermediate2, TRUE, FALSE))) {
    Handle2 = ConvertHandleIndexToHandle ((UINTN)Intermediate2);
  } else {
    Handle2 = NULL;
  }

  if (Param3 && !EFI_ERROR (ShellConvertStringToUint64 (Param3, &Intermediate3, TRUE, FALSE))) {
    Handle3 = ConvertHandleIndexToHandle ((UINTN)Intermediate3);
  } else {
    Handle3 = NULL;
  }

  if ((Param1 != NULL) && (Handle1 == NULL)) {
    ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"disconnect", Param1);
    return SHELL_INVALID_PARAMETER;
  } else if ((Param2 != NULL) && (Handle2 == NULL)) {
    ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"disconnect", Param2);
    return SHELL_INVALID_PARAMETER;
  } else if ((Param3 != NULL) && (Handle3 == NULL)) {
    ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"disconnect", Param3);
    return SHELL_INVALID_PARAMETER;
  } else if ((Handle2 != NULL) && EFI_ERROR (gBS->OpenProtocol (Handle2, &gEfiDriverBindingProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
    ASSERT (Param2 != NULL);
    ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_HANDLE_NOT), gShellDriver1HiiHandle, L"disconnect", ShellStrToUintn (Param2), L"driver handle");
    return SHELL_INVALID_PARAMETER;
  }

  ASSERT (Param1 != NULL);
  Status = gBS->DisconnectController (Handle1, Handle2, Handle3);
  ShellPrintHiiDefaultEx (STRING_TOKEN (STR_3P_RESULT), gShellDriver1HiiHandle, L"Disconnect", (UINTN)Intermediate1, (UINTN)Intermediate2, (UINTN)Intermediate3, Status);

  if (Status == EFI_SECURITY_VIOLATION) {
    ShellStatus = SHELL_SECURITY_VIOLATION;
  } else if (Status == EFI_INVALID_PARAMETER) {
    ShellStatus = SHELL_INVALID_PARAMETER;
  } else if (EFI_ERROR (Status)) {
    ShellStatus = SHELL_NOT_FOUND;
  }

  return ShellStatus;
}

/**
  Function for 'disconnect' 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
ShellCommandRunDisconnect (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS    Status;
  LIST_ENTRY    *Package;
  CHAR16        *ProblemParam;
  SHELL_STATUS  ShellStatus;

  ShellStatus = SHELL_SUCCESS;

  //
  // initialize the shell lib (we must be in non-auto-init...)
  //
  Status = ShellInitialize ();
  ASSERT_EFI_ERROR (Status);

  Status = CommandInit ();
  ASSERT_EFI_ERROR (Status);

  //
  // parse the command line
  //
  Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
  if (EFI_ERROR (Status)) {
    if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {
      ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"disconnect", ProblemParam);
      FreePool (ProblemParam);
      ShellStatus = SHELL_INVALID_PARAMETER;
    } else {
      ASSERT (FALSE);
    }

    return ShellStatus;
  }

  ShellStatus = MainCmdDisconnect (Package);
  ShellCommandLineFreeVarList (Package);

  return (ShellStatus);
}
