玩转Mac OS之UEFI(二)----SimpleUefiLog

Simple_Uefi_Log

version:1.0.0

UefiLog.h



#include 
#include 
#include 

#define LOG_DEBUG(Format, ...) Log(DEBUG, __FILE__, __func__, __LINE__, Format, ##__VA_ARGS__)
#define LOG_TRACE(Format, ...) Log(TRACE, __FILE__, __func__, __LINE__, Format, ##__VA_ARGS__)
#define LOG_INFO(Format, ...) Log(INFO, __FILE__, __func__, __LINE__, Format, ##__VA_ARGS__)
#define LOG_WRAN(Format, ...) Log(WRAN, __FILE__, __func__, __LINE__, Format, ##__VA_ARGS__)
#define LOG_ERROR(Format, ...) Log(ERROR, __FILE__, __func__, __LINE__, Format, ##__VA_ARGS__)

typedef enum _LOG_LEVEL
{
    DEBUG = 1,
    TRACE,
    INFO,
    WRAN,
    ERROR
}LOG_LEVEL;

// 使用前初始化日志库
// Path  可以传入NULL,则log文件和程序同目录
// Path  非NULL时,需保证上级目录存在
EFI_STATUS
LogInit(
        IN CHAR16 *Path
        );

// 程序结束前调用,用来关闭打开的Log文件
VOID
LogClose(
         VOID
         );

VOID
SetShowLevel(
             BOOLEAN Is                // default 'true'
);

VOID
SetShowLine(
            BOOLEAN Is                // default 'true'
);

VOID
SetShowFuncName(
                BOOLEAN Is                // default 'true'
);

VOID
SetShowFileName(
                BOOLEAN Is                // default 'false'
);

VOID
SetShowTime(
            BOOLEAN Is                // default 'true'
);

VOID
Log(
    LOG_LEVEL level,
    CHAR8 *FileName,
    CHAR8 *FuncName,
    UINTN LineNum,
    CHAR16 *Format,
    ...
    );

UefiLog.c


#include "UefiLog.h"

#include 
#include 
#include 
#include 
#include 

#include 
#include 

#include 

#define MAX_MSG_SIZE  0x200

EFI_FILE_PROTOCOL *gFileHandle = NULL;
STATIC BOOLEAN ShowLevel = TRUE;
STATIC BOOLEAN ShowLine = TRUE;
STATIC BOOLEAN ShowFuncName = TRUE;
STATIC BOOLEAN ShowFileName = FALSE;
STATIC BOOLEAN ShowTime = TRUE;

VOID
SetShowLevel(
    BOOLEAN Is
)
{
    ShowLevel = Is;
}

VOID
SetShowLine(
    BOOLEAN Is
) 
{
    ShowLine = Is;
}

VOID
SetShowFuncName(
    BOOLEAN Is
)
{
    ShowFuncName = Is;
}

VOID
SetShowFileName(
    BOOLEAN Is
)
{
    ShowFileName = Is;
}

VOID
SetShowTime(
    BOOLEAN Is
)
{
    ShowTime = Is;
}

CHAR16 *
GetLevelString(
    LOG_LEVEL Level
)
{
    switch (Level)
    {
    case DEBUG:
        return L"[ DEBUG ]";
    case TRACE:
        return L"[ TRACE ]";
    case INFO:
        return L"[ INFO ]";
    case WRAN:
        return L"[ WARN ]";
    case ERROR:
        return L"[ ERROR ]";
    default:
        return L"[       ]";
        break;
    }
}

CHAR16 *
GetEfiTime(
    VOID
)
{
    EFI_TIME Time;
    EFI_STATUS Status;
    CHAR16 *TimeStr = NULL;
    Status = gRT->GetTime(
        &Time, 
        NULL
    );
    if (EFI_ERROR(Status))
    {
        Print(L"Get Time Failed: %r\n", Status);
        return L"1970-01-01 00:00:00";
    }

    TimeStr = CatSPrint(
        TimeStr,
        L"%d-%02d-%02d %02d:%02d:%02d",
        Time.Year,
        Time.Month,
        Time.Day,
        Time.Hour,
        Time.Minute,
        Time.Second
    );
    return TimeStr;
}

CHAR16 *
GetStrReplace(
    IN CHAR16 *Str,
    IN CHAR16 *OldStr,
    IN CHAR16 *NewStr
)
{
    UINTN LenStr;
    UINTN OldStrLen;
    UINTN Index = 0;
    CHAR16 *BStr = NULL;

    LenStr = StrLen(Str);
    OldStrLen = StrLen(OldStr);

    BStr = AllocatePool(LenStr);
    gBS->SetMem(
        BStr, 
        LenStr,
        0
    );

    for (Index = 0; Index < LenStr; Index++)
    {
        if (!StrnCmp(
            Str + Index, 
            OldStr, 
            OldStrLen
        ))
        {
            StrCat(
                BStr, 
                NewStr
            );
            Index += OldStrLen - 1;
        }
        else
        {
            StrnCat(
                BStr, 
                Str + Index, 
                1
            );
        }
    }

    StrCpy(
        Str, 
        BStr
    );

    return Str;
}

EFI_STATUS
GetCurrentPath(
    OUT CHAR16 **Path
)
{
    EFI_STATUS Status;
    EFI_LOADED_IMAGE_PROTOCOL *LoadedImageProtocol;
    EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevicePathToTextProtocol;
    
    Status = gBS->LocateProtocol(
        &gEfiDevicePathToTextProtocolGuid, 
        NULL, 
        (VOID **)&DevicePathToTextProtocol
    );
    if (EFI_ERROR(Status))
    {
        Print(L"Get DevicePathToTextProtocol Error: %r\n", Status);
        return Status;
    }

    Status = gBS->HandleProtocol(
        gImageHandle, 
        &gEfiLoadedImageProtocolGuid, 
        (VOID **)&LoadedImageProtocol
    );
    if (EFI_ERROR(Status))
    {
        Print(L"Get LoadedImageProtocol Error: %r\n", Status);
        return Status;
    }

    *Path = DevicePathToTextProtocol->ConvertDevicePathToText(
        LoadedImageProtocol->FilePath,
        TRUE,
        TRUE
    );

    return EFI_SUCCESS;
}

EFI_STATUS
OpenLogFile(
    OUT EFI_FILE_PROTOCOL **FileHandle,
    IN CHAR16 *Path
)
{
    EFI_STATUS Status;
    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystemProtocol;
    EFI_FILE_PROTOCOL *Root = 0;

    Status = gBS->LocateProtocol(
        &gEfiSimpleFileSystemProtocolGuid,
        NULL,
        (VOID **)&SimpleFileSystemProtocol
    );

    if (EFI_ERROR(Status))
    {
        Print(L"Get SimpleFileSystemProtocol Error: %r\n", Status);
        return Status;
    }

    Status = SimpleFileSystemProtocol->OpenVolume(
        SimpleFileSystemProtocol,
        &Root
    );

    if (EFI_ERROR(Status))
    {
        Print(L"OpenVolume Failed : %r\n", Status);
        return Status;
    }

    Status = Root->Open(
        Root,
        FileHandle,
        Path,
        EFI_FILE_MODE_CREATE |
        EFI_FILE_MODE_WRITE |
        EFI_FILE_MODE_READ,
        0
    );

    if (EFI_ERROR(Status))
    {
        Print(L"Open File Failed : %r\n", Status);
        return Status;
    }

    return EFI_SUCCESS;
}


EFI_STATUS
LogInit(
    IN CHAR16 *Path
)
{
    EFI_STATUS Status;
    if (Path == NULL)
    {
        Status = GetCurrentPath(&Path);
        Path = GetStrReplace(Path, L".efi", L".log");
        if (EFI_ERROR(Status))
        {
            Print(L"GetCurrentPathError: %r\n", Status);
            return Status;
        }
    }

    Status = OpenLogFile(
        &gFileHandle, 
        Path
    );

    return Status;
}

EFI_STATUS
WriteData(
    IN VOID *Buffer,
    IN UINT64 BufferSize
)
{
    if (gFileHandle == NULL)
    {
        Print(L"Unknow File!\n");
        return EFI_UNSUPPORTED;
    }

    if (Buffer == NULL)
    {
        Print(L"Unknow Buffer!\n");
        return EFI_UNSUPPORTED;
    }

    if (BufferSize == 0)
    {
        Print(L"Unknow BufferSize!\n");
        return EFI_UNSUPPORTED;
    }

    EFI_STATUS Status;
    UINTN InfoBufferSize;
    EFI_FILE_INFO *FileInfo = NULL;

    Status = gFileHandle->GetInfo(
        gFileHandle,
        &gEfiFileInfoGuid, 
        &InfoBufferSize, 
        (VOID *)FileInfo
    );

    if (Status == EFI_BUFFER_TOO_SMALL)
    {
        FileInfo = AllocatePool(InfoBufferSize);
        Status = gFileHandle->GetInfo(
            gFileHandle,
            &gEfiFileInfoGuid,
            &InfoBufferSize,
            (VOID *)FileInfo
        );
    }

    if (EFI_ERROR(Status))
    {
        Print(L"Get File Info Failed: %r\n", Status);
        return Status;
    }

    Status = gFileHandle->SetPosition(
        gFileHandle,
        FileInfo->FileSize
    );

    if (EFI_ERROR(Status))
    {
        Print(L"Set Position Failed: %r\n", Status);
        return Status;
    }

    Status = gFileHandle->Write(
        gFileHandle,
        &BufferSize,
        Buffer
    );
    if (EFI_ERROR(Status))
    {
        Print(L"Write File Failed: %r\n", Status);
        return Status;
    }

    Status = gFileHandle->Flush(gFileHandle);

    if (EFI_ERROR(Status))
    {
        Print(L"Flush Data Failed: %r\n", Status);
        return Status;
    }
    return Status;
}

VOID
LogClose(
    VOID
)
{
    gFileHandle->Flush(gFileHandle);
    gFileHandle->Close(gFileHandle);
}

VOID
Log(
    LOG_LEVEL level,
    CHAR8 *FileName,
    CHAR8 *FuncName,
    UINTN LineNum,
    CHAR16 *Format,
    ...
)
{
    VA_LIST Marker;
    CHAR16 Buffer[MAX_MSG_SIZE];
    CHAR16 *Header = NULL;
    CHAR16 *Data = NULL;

    VA_START(
        Marker, 
        Format
    );
    UnicodeVSPrint(
        Buffer, 
        MAX_MSG_SIZE, 
        Format, 
        Marker
    );
    VA_END(Marker);

    if (ShowLevel)
    {
        Header = CatSPrint(
            Header, 
            L"%s ", 
            GetLevelString(level)
        );
    }

    if (ShowTime)
    {
        Header = CatSPrint(
            Header,
            L"%s ",
            GetEfiTime()
        );
    }

    if (ShowFileName)
    {
        Header = CatSPrint(
            Header,
            L"%a ",
            FileName
        );
    }

    if (ShowFuncName)
    {
        Header = CatSPrint(
            Header,
            L"%a ",
            FuncName
        );
    }

    if (ShowLine)
    {
        Header = CatSPrint(
            Header,
            L"%d ",
            LineNum
        );
    }

    if (Header == NULL)
    {
        Header = L"";
    }

    Data = CatSPrint(
        Data, 
        L"%s%s",
        Header,
        Buffer
    );

    Print(L"%s", Data);
    WriteData((VOID *)Data, StrLen(Data) * 2);
}

UefiLog是在UEFI环境下轻量级日志系统

1.

在使用宏定义前调用LogInit()进行初始化日志库
在程序退出前调用LogClose()关闭日志库

// 使用前初始化日志库
// Path  可以传入NULL,则log文件和程序同目录
// Path  非NULL时,需保证上级目录存在
EFI_STATUS
LogInit(
    IN CHAR16 *Path
);

2.

可以调用SetShowLevel()来选择是否显示日志级别
相关设置有 行数、函数名称、文件名、时间、日志级别
默认不显示文件名。

Test.c

//
// UefiLog
//
// test.c 
//
// UefiLog test Application
//

#include 
#include 
#include 
#include 
#include "UefiLog/UefiLog.h"

EFI_STATUS
EFIAPI
UefiMain(
    IN EFI_HANDLE ImageHandle,
    IN EFI_SYSTEM_TABLE* SystemTable
)
{
    LogInit(NULL);
    LOG_DEBUG(L"Test:%r\n", EFI_SUCCESS);
    SetShowFileName(TRUE);
    LOG_ERROR(L"error:%r\n", EFI_LOAD_ERROR);
    SetShowLevel(FALSE);
    SetShowFileName(FALSE);
    SetShowFuncName(FALSE);
    SetShowLine(FALSE);
    SetShowTime(FALSE);

    CHAR8 Data[] = {
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    };

    UINTN Index = 0;

    for (Index = 0; Index < 512; Index++)
    {
        if (Index % 16 == 0)
        {
            LOG_DEBUG(L"%04X:   ", Index);
        }

        LOG_DEBUG(L"%02X  ", Data[Index]);

        if (Index % 16 == 15)
        {
            LOG_DEBUG(L"\n");
        }
    }
    LogClose();
    return EFI_SUCCESS;
}

3.

才疏学浅,能力有限,望指正!

4.

关注GitHub or 不断更新中!

飞机票:SimpleUefiLog

你可能感兴趣的:(玩转Mac OS之UEFI(二)----SimpleUefiLog)