/** @file

Copyright (c) 2007, 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
http://opensource.org/licenses/bsd-license.php

THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

**/

#ifndef _EFI_EDB_COMMON_H_
#define _EFI_EDB_COMMON_H_

#include <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/Ebc.h>
#include <Protocol/EbcVmTest.h>
#include <Protocol/DebugSupport.h>
#include <Protocol/PciRootBridgeIo.h>
#include <Protocol/SimpleFileSystem.h>
#include <Protocol/DebuggerConfiguration.h>
#include <Guid/FileInfo.h>
#include <Guid/FileSystemInfo.h>
#include <Guid/FileSystemVolumeLabelInfo.h>
#include <Guid/DebugImageInfoTable.h>

typedef UINTN EFI_DEBUG_STATUS;

typedef struct _EFI_DEBUGGER_PRIVATE_DATA EFI_DEBUGGER_PRIVATE_DATA;

//
// Definition for Debugger Command
//
typedef
EFI_DEBUG_STATUS
(* EFI_DEBUGGER_COMMAND) (
  IN     CHAR16                    *CommandArg,
  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
  IN     EFI_EXCEPTION_TYPE        ExceptionType,
  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
);

typedef struct {
  CHAR16                *CommandName;
  CHAR16                *CommandTitle;
  CHAR16                *CommandHelp;
  CHAR16                *CommandSyntax;
  CHAR16                *ClassName;
  EFI_INPUT_KEY         CommandKey;
  EFI_DEBUGGER_COMMAND  CommandFunc;
} EFI_DEBUGGER_COMMAND_SET;

//
// Definition for Debugger Symbol
//
#define EFI_DEBUGGER_SYMBOL_NAME_MAX     256
#define EFI_DEBUGGER_SYMBOL_ENTRY_MAX    512
#define EFI_DEBUGGER_SYMBOL_OBJECT_MAX   32

//
// We have following SYMBOL data structure:
//
// SYMBOL_CONTEXT -> SYMBOL_OBJECT -> SYMBOL_ENTRY (FuncXXX, 0xXXX)
//                                    SYMBOL_ENTRY (VarYYY,  0xYYY)
//                                    SYMBOL_ENTRY
//
//                   SYMBOL_OBJECT -> SYMBOL_ENTRY
//                                    SYMBOL_ENTRY
//
//                   SYMBOL_OBJECT -> SYMBOL_ENTRY
//                                    SYMBOL_ENTRY
//

typedef enum {
  EfiDebuggerSymbolFunction,
  EfiDebuggerSymbolStaticFunction,
  EfiDebuggerSymbolGlobalVariable,
  EfiDebuggerSymbolStaticVariable,
  EfiDebuggerSymbolTypeMax,
} EFI_DEBUGGER_SYMBOL_TYPE;

typedef struct {
  CHAR8                      Name[EFI_DEBUGGER_SYMBOL_NAME_MAX];
  UINTN                      Rva;
  EFI_DEBUGGER_SYMBOL_TYPE   Type;
  CHAR8                      ObjName[EFI_DEBUGGER_SYMBOL_NAME_MAX];
  CHAR8                      *CodBuffer;
  UINTN                      CodBufferSize;
  UINTN                      FuncOffsetBase;
  CHAR8                      *SourceBuffer;
} EFI_DEBUGGER_SYMBOL_ENTRY;

typedef struct {
  CHAR16                     Name[EFI_DEBUGGER_SYMBOL_NAME_MAX];
  UINTN                      EntryCount;
  UINTN                      MaxEntryCount;
  UINTN                      BaseAddress;
  UINTN                      StartEntrypointRVA;
  UINTN                      MainEntrypointRVA;
  EFI_DEBUGGER_SYMBOL_ENTRY  *Entry;
  VOID                       **SourceBuffer;
} EFI_DEBUGGER_SYMBOL_OBJECT;

typedef struct {
  UINTN                       ObjectCount;
  UINTN                       MaxObjectCount;
  EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
  BOOLEAN                     DisplaySymbol;
  BOOLEAN                     DisplayCodeOnly;
} EFI_DEBUGGER_SYMBOL_CONTEXT;

//
// Definition for Debugger Breakpoint
//
#define EFI_DEBUGGER_BREAKPOINT_MAX    0x10

typedef struct {
  EFI_PHYSICAL_ADDRESS      BreakpointAddress;
  UINT64                    OldInstruction;    // UINT64 is enough for an instruction
  BOOLEAN                   State;
} EFI_DEBUGGER_BREAKPOINT_CONTEXT;

//
// Definition for Debugger Call-Stack
//
#define EFI_DEBUGGER_CALLSTACK_MAX     0x10

typedef enum {
  EfiDebuggerBranchTypeEbcCall,
  EfiDebuggerBranchTypeEbcCallEx,
  EfiDebuggerBranchTypeEbcRet,
  EfiDebuggerBranchTypeEbcJmp,
  EfiDebuggerBranchTypeEbcJmp8,
  EfiDebuggerBranchTypeEbcMax,
} EFI_DEBUGGER_BRANCH_TYPE;

#define EFI_DEBUGGER_CALL_MAX_PARAMETER      0x16
#define EFI_DEBUGGER_CALL_DEFAULT_PARAMETER  0x8

typedef struct {
  EFI_PHYSICAL_ADDRESS      SourceAddress;
  EFI_PHYSICAL_ADDRESS      DestAddress;
  //
  // We save all parameter here, because code may update the parameter as local variable.
  //
  UINTN                     ParameterAddr;
  UINTN                     Parameter[EFI_DEBUGGER_CALL_MAX_PARAMETER];
  EFI_DEBUGGER_BRANCH_TYPE  Type;
} EFI_DEBUGGER_CALLSTACK_CONTEXT;

//
// Definition for Debugger Trace
//
#define EFI_DEBUGGER_TRACE_MAX         0x10

typedef struct {
  EFI_PHYSICAL_ADDRESS      SourceAddress;
  EFI_PHYSICAL_ADDRESS      DestAddress;
  EFI_DEBUGGER_BRANCH_TYPE  Type;
} EFI_DEBUGGER_TRACE_CONTEXT;

//
// Definition for Debugger Step
//
typedef struct {
  EFI_PHYSICAL_ADDRESS      BreakAddress;
  EFI_PHYSICAL_ADDRESS      FramePointer;
} EFI_DEBUGGER_STEP_CONTEXT;

//
// Definition for Debugger GoTil
//
typedef struct {
  EFI_PHYSICAL_ADDRESS      BreakAddress;
} EFI_DEBUGGER_GOTIL_CONTEXT;

//
// Definition for Debugger private data structure
//
#define EFI_DEBUGGER_SIGNATURE         SIGNATURE_32 ('e', 'd', 'b', '!')

#define EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER  5

#define EFI_DEBUG_BREAK_TIMER_INTERVAL        10000000   // 1 second

#define EFI_DEBUG_FLAG_EBC            0x80000000
#define EFI_DEBUG_FLAG_EBC_B_BOC      0x1
#define EFI_DEBUG_FLAG_EBC_B_BOCX     0x2
#define EFI_DEBUG_FLAG_EBC_B_BOR      0x4
#define EFI_DEBUG_FLAG_EBC_B_BOE      0x8
#define EFI_DEBUG_FLAG_EBC_B_BOT      0x10
#define EFI_DEBUG_FLAG_EBC_B_STEPOVER 0x20
#define EFI_DEBUG_FLAG_EBC_B_STEPOUT  0x40
#define EFI_DEBUG_FLAG_EBC_B_BP       0x80
#define EFI_DEBUG_FLAG_EBC_B_GT       0x100
#define EFI_DEBUG_FLAG_EBC_B_BOK      0x200
#define EFI_DEBUG_FLAG_EBC_BOC        (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_BOC)
#define EFI_DEBUG_FLAG_EBC_BOCX       (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_BOCX)
#define EFI_DEBUG_FLAG_EBC_BOR        (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_BOR)
#define EFI_DEBUG_FLAG_EBC_BOE        (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_BOE)
#define EFI_DEBUG_FLAG_EBC_BOT        (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_BOT)
#define EFI_DEBUG_FLAG_EBC_STEPOVER   (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_STEPOVER)
#define EFI_DEBUG_FLAG_EBC_STEPOUT    (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_STEPOUT)
#define EFI_DEBUG_FLAG_EBC_BP         (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_BP)
#define EFI_DEBUG_FLAG_EBC_GT         (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_GT)
#define EFI_DEBUG_FLAG_EBC_BOK        (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_BOK)

//
// Debugger private data structure
//
typedef struct _EFI_DEBUGGER_PRIVATE_DATA {
  UINT32                                      Signature;
  EFI_INSTRUCTION_SET_ARCHITECTURE            Isa;
  UINT32                                      EfiDebuggerRevision;
  UINT32                                      EbcVmRevision;
  EFI_DEBUGGER_CONFIGURATION_PROTOCOL         DebuggerConfiguration;
  EFI_DEBUG_IMAGE_INFO_TABLE_HEADER           *DebugImageInfoTableHeader;
  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL             *Vol;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL             *PciRootBridgeIo;
  EFI_DEBUGGER_COMMAND_SET                    *DebuggerCommandSet;
  EFI_DEBUGGER_SYMBOL_CONTEXT                 DebuggerSymbolContext;
  UINTN                                       DebuggerBreakpointCount;
  EFI_DEBUGGER_BREAKPOINT_CONTEXT             DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX + 1];
  UINTN                                       CallStackEntryCount;
  EFI_DEBUGGER_CALLSTACK_CONTEXT              CallStackEntry[EFI_DEBUGGER_CALLSTACK_MAX + 1];
  UINTN                                       TraceEntryCount;
  EFI_DEBUGGER_TRACE_CONTEXT                  TraceEntry[EFI_DEBUGGER_TRACE_MAX + 1];
  EFI_DEBUGGER_STEP_CONTEXT                   StepContext;
  EFI_DEBUGGER_GOTIL_CONTEXT                  GoTilContext;
  EFI_PHYSICAL_ADDRESS                        InstructionScope;
  UINTN                                       InstructionNumber;
  UINT32                                      FeatureFlags;
  UINT32                                      StatusFlags;
  BOOLEAN                                     EnablePageBreak;
  EFI_EVENT                                   BreakEvent;
} EFI_DEBUGGER_PRIVATE_DATA;

#endif
