玩轉(zhuǎn)Mac OS之UEFI(二)----SimpleUefiLog

Simple_Uefi_Log

version:1.0.0

UefiLog.h



#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Protocol/SimpleFileSystem.h>

#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;

// 使用前初始化日志庫(kù)
// Path  可以傳入NULL蚯根,則log文件和程序同目錄
// Path  非NULL時(shí)树绩,需保證上級(jí)目錄存在
EFI_STATUS
LogInit(
        IN CHAR16 *Path
        );

// 程序結(jié)束前調(diào)用训桶,用來(lái)關(guān)閉打開(kāi)的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 <Library/BaseLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>

#include <Protocol/LoadedImage.h>
#include <Protocol/DevicePathToText.h>

#include <Guid/FileInfo.h>

#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環(huán)境下輕量級(jí)日志系統(tǒng)

1.

在使用宏定義前調(diào)用LogInit()進(jìn)行初始化日志庫(kù)
在程序退出前調(diào)用LogClose()關(guān)閉日志庫(kù)

// 使用前初始化日志庫(kù)
// Path  可以傳入NULL匿刮,則log文件和程序同目錄
// Path  非NULL時(shí)典蜕,需保證上級(jí)目錄存在
EFI_STATUS
LogInit(
    IN CHAR16 *Path
);

2.

可以調(diào)用SetShowLevel()來(lái)選擇是否顯示日志級(jí)別
相關(guān)設(shè)置有 行數(shù)笤喳、函數(shù)名稱(chēng)间校、文件名、時(shí)間教寂、日志級(jí)別
默認(rèn)不顯示文件名捏鱼。

Test.c

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

#include <Uefi.h>
#include <Library/DebugLib.h>
#include <Library/PrintLib.h>
#include <Library/BaseLib.h>
#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.

才疏學(xué)淺,能力有限酪耕,望指正穷躁!

4.

關(guān)注GitHub or 簡(jiǎn)書(shū) 不斷更新中!

飛機(jī)票:SimpleUefiLog

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末因妇,一起剝皮案震驚了整個(gè)濱河市问潭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌婚被,老刑警劉巖狡忙,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異址芯,居然都是意外死亡灾茁,警方通過(guò)查閱死者的電腦和手機(jī)窜觉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)北专,“玉大人禀挫,你說(shuō)我怎么就攤上這事⊥赝牵” “怎么了语婴?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)驶睦。 經(jīng)常有香客問(wèn)我砰左,道長(zhǎng),這世上最難降的妖魔是什么场航? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任缠导,我火速辦了婚禮,結(jié)果婚禮上溉痢,老公的妹妹穿的比我還像新娘僻造。我一直安慰自己,他們只是感情好孩饼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布髓削。 她就那樣靜靜地躺著,像睡著了一般捣辆。 火紅的嫁衣襯著肌膚如雪蔬螟。 梳的紋絲不亂的頭發(fā)上此迅,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天汽畴,我揣著相機(jī)與錄音,去河邊找鬼耸序。 笑死忍些,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的坎怪。 我是一名探鬼主播罢坝,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼搅窿!你這毒婦竟也來(lái)了嘁酿?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤男应,失蹤者是張志新(化名)和其女友劉穎闹司,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體沐飘,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡游桩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年牲迫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片借卧。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盹憎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出铐刘,到底是詐尸還是另有隱情陪每,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布滨达,位于F島的核電站奶稠,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏捡遍。R本人自食惡果不足惜锌订,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望画株。 院中可真熱鬧辆飘,春花似錦、人聲如沸谓传。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)续挟。三九已至紧卒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間诗祸,已是汗流浹背跑芳。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留直颅,地道東北人博个。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像功偿,于是被迫代替她去往敵國(guó)和親盆佣。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容