VBoxDebugLib.c revision 8075cc001549198c1002b13c720c274814b8397c
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/* $Id$ */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/** @file
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * VBoxDebugLib.c - Debug logging and assertions support routines using DevEFI.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/*
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Copyright (C) 2009-2012 Oracle Corporation
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync *
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * available from http://www.virtualbox.org. This file is free software;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * you can redistribute it and/or modify it under the terms of the GNU
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * General Public License (GPL) as published by the Free Software
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync *
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * The contents of this file may alternatively be used under the terms
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * of the Common Development and Distribution License Version 1.0
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * VirtualBox OSE distribution, in which case the provisions of the
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * CDDL are applicable instead of those of the GPL.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync *
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * You may elect to license modified versions of this file under the
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * terms and conditions of either the GPL or the CDDL or both.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/*******************************************************************************
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync* Header Files *
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync*******************************************************************************/
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#include <Base.h>
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#include <Library/PrintLib.h>
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#include <Library/DebugLib.h>
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#include "VBoxDebugLib.h"
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#include <Protocol/DevicePath.h>
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#include <Protocol/DevicePathToText.h>
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#include <Uefi/UefiSpec.h>
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#include <Library/UefiBootServicesTableLib.h>
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#include "DevEFI.h"
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#if 0
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncstatic EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *g_DevPath2Txt;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#endif
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
6dd8f5023a9ba7588212331db90059553136fe33vboxsyncVOID EFIAPI
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncDebugPrint(IN UINTN ErrorLevel, IN CONST CHAR8 *Format, ...)
9127c416edfd6f9266e387f7abd7aa9904eecbc9vboxsync{
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync CHAR8 szBuf[256];
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync VA_LIST va;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync UINTN cch;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync RTCCUINTREG SavedFlags;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
9127c416edfd6f9266e387f7abd7aa9904eecbc9vboxsync /* No pool noise, please. */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (ErrorLevel == DEBUG_POOL)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync return;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync VA_START(va, Format);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync cch = AsciiVSPrint(szBuf, sizeof(szBuf), Format, va);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync VA_END(va);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* make sure it's terminated and doesn't end with a newline */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (cch >= sizeof(szBuf))
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync cch = sizeof(szBuf) - 1;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync while (cch > 0 && (szBuf[cch - 1] == '\n' || szBuf[cch - 1] == '\r'))
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync cch--;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync szBuf[cch] = '\0';
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* Output the log string. */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync SavedFlags = ASMIntDisableFlags();
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync VBoxPrintString("dbg/");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync VBoxPrintHex(ErrorLevel, sizeof(ErrorLevel));
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync VBoxPrintChar(' ');
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync VBoxPrintString(szBuf);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync VBoxPrintChar('\n');
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync ASMSetFlags(SavedFlags);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync}
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/**
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Our own log worker function, avoid the dbg/00000xxx prefix and makes it clear
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * which log statements we added..
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync *
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pszFormat Format string. EFI style!
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param ... Argument referneced in the format string.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncVOID EFIAPI
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncVBoxLogWorker(const char *pszFormat, ...)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync{
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync CHAR8 szBuf[384];
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync VA_LIST va;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync RTCCUINTREG SavedFlags;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* Format it. */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync VA_START(va, pszFormat);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync AsciiVSPrint(szBuf, sizeof(szBuf), pszFormat, va);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync VA_END(va);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync szBuf[sizeof(szBuf) - 1] = '\0';
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* Output the log string. */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync SavedFlags = ASMIntDisableFlags();
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync VBoxPrintString(szBuf);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync VBoxPrintChar('\n');
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync ASMSetFlags(SavedFlags);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync}
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/**
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Adds a character to the panic message.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync *
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param ch The ASCII char to add.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncstatic void
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncVBoxPanicMsgChar(int ch)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync{
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync ASMOutU16(EFI_PANIC_PORT, EFI_PANIC_CMD_MSG_FROM_CHAR(ch));
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync}
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/**
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Adds a string to the panic message.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync *
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pszString The string to add.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncstatic void
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncVBoxPanicMsgString(const char *pszString)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync{
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync char ch;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync while ((ch = *pszString++) != '\0')
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync VBoxPanicMsgChar(ch);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync}
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/**
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Adds a unsigned decimal number to the panic message.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync *
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param uValue The value.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncstatic void
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncVBoxPanicMsgDecimalU32(uint32_t uValue)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync{
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync char szTmp[32];
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync unsigned off = sizeof(szTmp) - 1;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync szTmp[off] = '\0';
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync do
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync {
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync char chDigit = uValue % 10;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync uValue /= 10;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync szTmp[--off] = chDigit + '0';
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync } while (uValue != 0 && off > 0);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync VBoxPanicMsgString(&szTmp[off]);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync}
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncVOID EFIAPI
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncDebugAssert(IN CONST CHAR8 *FileName, IN UINTN LineNumber, IN CONST CHAR8 *Description)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync{
RTCCUINTREG SavedFlags = ASMIntDisableFlags();
ASMOutU8(EFI_PANIC_PORT, EFI_PANIC_CMD_START_MSG);
VBoxPanicMsgString("EFI Assertion failed!"
"\nFile: ");
VBoxPanicMsgString(FileName ? FileName : "<NULL>");
VBoxPanicMsgString("\nLine: ");
VBoxPanicMsgDecimalU32((uint32_t)LineNumber);
VBoxPanicMsgString("\nEDescription: ");
VBoxPanicMsgString(Description ? Description : "<NULL>");
ASMOutU8(EFI_PANIC_PORT, EFI_PANIC_CMD_END_MSG);
ASMSetFlags(SavedFlags);
}
CHAR16 *VBoxDebugDevicePath2Str(IN EFI_DEVICE_PATH_PROTOCOL *pDevicePath)
{
#if 0
EFI_STATUS rc;
if (!g_DevPath2Txt)
{
rc = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&g_DevPath2Txt);
if (EFI_ERROR(rc))
{
DEBUG((DEBUG_INFO, "gEfiDevicePathToTextProtocolGuid:%g isn't instantied\n", gEfiDevicePathToTextProtocolGuid));
return NULL;
}
}
return g_DevPath2Txt->ConvertDevicePathToText(pDevicePath, TRUE, FALSE);
#else
return NULL;
#endif
}
CHAR16 *VBoxDebugHandleDevicePath2Str(IN EFI_HANDLE hHandle)
{
#if 0
EFI_STATUS rc;
EFI_DEVICE_PATH_PROTOCOL *pDevicePath = NULL;
CHAR16 *psz16TxtDevicePath;
rc = gBS->OpenProtocol(hHandle,
&gEfiDevicePathProtocolGuid,
(VOID **)pDevicePath,
NULL,
hHandle,
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
if (EFI_ERROR(rc))
{
DEBUG((DEBUG_INFO, "%a:%d failed(%r) to open Device Path Protocol for Handle %p\n",
__FUNCTION__,
__LINE__,
rc,
hHandle));
return NULL;
}
psz16TxtDevicePath = VBoxDebugHandleDevicePath2Str(pDevicePath);
return psz16TxtDevicePath;
#else
return NULL;
#endif
}
CHAR16 *VBoxDebugPrintDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *pDevicePath)
{
#if 0
EFI_STATUS rc;
if (!g_DevPath2Txt)
{
rc = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&g_DevPath2Txt);
if (EFI_ERROR(rc))
{
DEBUG((DEBUG_INFO, "gEfiDevicePathToTextProtocolGuid:%g isn't instantied\n", gEfiDevicePathToTextProtocolGuid));
return NULL;
}
}
return g_DevPath2Txt->ConvertDevicePathToText(pDevicePath, TRUE, FALSE);
#else
return NULL;
#endif
}
VOID * EFIAPI
DebugClearMemory(OUT VOID *Buffer, IN UINTN Length)
{
return Buffer;
}
BOOLEAN EFIAPI
DebugAssertEnabled(VOID)
{
return TRUE;
}
BOOLEAN EFIAPI
DebugPrintEnabled(VOID)
{
/** @todo some PCD for this so we can disable it in release builds. */
return TRUE;
}
BOOLEAN EFIAPI
DebugCodeEnabled(VOID)
{
/** @todo ditto */
return TRUE;
}
BOOLEAN EFIAPI
DebugClearMemoryEnabled(VOID)
{
return FALSE;
}