【UEFI实战】BIOS下的JSON
迪丽瓦拉
2025-05-31 02:02:16
0次

JSON简述

关于JSON的描述:

  • JSON是存储和传输数据的格式。
  • JSON经常在数据从服务器发送到网页时使用。
  • JSON指的是 JavaScript Object Notation。
  • JSON是轻量级的数据交换格式。
  • JSON独立于语言。
  • JSON是“自描述的”且易于理解。

当数据在浏览器与服务器之间进行交换时,这些数据只能是文本。JSON属于文本,并且我们能够把任何JavaScript对象转换为JSON,然后将JSON发送到服务器。我们也能把从服务器接收到的任何JSON转换为JavaScript对象。

JSON使用JavaScript语法,但是JSON格式是纯文本的。文本可被任何编程语言作为数据来读取和使用。

JSON与BIOS

目前EDK开源的代码中已经有对JSON的使用,它在RedfishPkg中体现:

PS D:\Gitee\edk2-beni\edk2> git submodule
-b64af41c3276f97f0e181920400ee056b9c88037 ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3
-f4153a09f87cbb9c826d8fc12c74642bb2d879ea BaseTools/Source/C/BrotliCompress/brotli
-d82e959e621a3d597f1e0d50ff8c2d8b96915fd7 CryptoPkg/Library/OpensslLib/openssl
-f4153a09f87cbb9c826d8fc12c74642bb2d879ea MdeModulePkg/Library/BrotliCustomDecompressLib/brotli
-abfc8ff81df4067f309032467785e06975678f0d MdeModulePkg/Universal/RegularExpressionDxe/oniguruma
-e9ebfa7e77a6bee77df44e096b100e7131044059 RedfishPkg/Library/JsonLib/jansson  # RedfishPkg中包含的子模块
-1cc9cde3448cdd2e000886a26acf1caac2db7cf1 UnitTestFrameworkPkg/Library/CmockaLib/cmocka
-86add13493e5c881d7e4ba77fb91c1f57752b3a4 UnitTestFrameworkPkg/Library/GoogleTestLib/googletest

它是JSON的c语言实现,对应的开源库是https://github.com/akheron/jansson.git。

之所以会在RedfishPkg中,是因为Redfish传输数据的最通用方式就是JSON,为了在BIOS下实现Redfish(目前正式的EDK开源代码中还没有包含),就需要处理JSON。在RedfishPkg中提供了JSON的操作接口,位于RedfishPkg\Include\Library\JsonLib.h,由于涉及到的函数很多,这里就不全部列出。

BIOS下使用JSON

本节介绍在BIOS下使用JSON的示例,最终的代码可以在https://gitee.com/jiangwei0512/edk2-beni.git找到。

  1. 首先创建一个简单的JSON文件(example.json):
{"name": "BENI","age": 18
}

我们会在Shell下操作它,所以需要将它放到FileSystem中,对应FS0:

在这里插入图片描述

  1. 然后在BIOS下包含JsonLib库:
JsonLib|RedfishPkg/Library/JsonLib/JsonLib.inf

该库还依赖于其它的一些库,比如Ucs2Utf8Lib、RedfishCrtLib等,也需要包含进去。

  1. 之后先一个Shell命令来测试该库,对应BeniPkg\DynamicCommand\TestDynamicCommand\TestDynamicCommand.inf。

这里需要注意一个问题,在JsonLib依赖的RedfishCrtLib会使用到另外的一个库BaseSortLib,而这个库Shell应用也需要用到(实际使用的是SortLib,但是两者对应的是一样的接口,但是实现不同),两者使用的是不同的代码实现,这导致了Shell命令需要使用的StringNoCaseCompare()被ASSERT,导致使用异常,这里的解决方式是修改RedfishCrtLib的实现(对应RedfishPkg\PrivateLibrary\RedfishCrtLib\RedfishCrtLib.inf):

[LibraryClasses]BaseLibSortLib	# 使用SortLib而不是BaseSortLibDebugLibMemoryAllocationLibUefiRuntimeServicesTableLib
  1. 之后就是代码的具体实现。

这里首先获取文件example.json:

  Status = ShellOpenFileByName (FileName,&FileHandle,EFI_FILE_MODE_READ,0);if (EFI_ERROR (Status)) {DEBUG ((EFI_D_ERROR, "[%a][%d] Failed. - %r\n", __FUNCTION__, __LINE__, Status));goto DONE;}Status = gEfiShellProtocol->GetFileSize (FileHandle, &FileSize);if (EFI_ERROR (Status)) {DEBUG ((EFI_D_ERROR, "[%a][%d] Failed. - %r\n", __FUNCTION__, __LINE__, Status));goto DONE;}Data = AllocateZeroPool (FileSize);if (NULL == Data) {DEBUG ((EFI_D_ERROR, "[%a][%d] Out of memory\n", __FUNCTION__, __LINE__));goto DONE;}Status = ShellReadFile (FileHandle, &FileSize, Data);if (EFI_ERROR (Status)) {DEBUG ((EFI_D_ERROR, "[%a][%d] Failed. - %r\n", __FUNCTION__, __LINE__, Status));return;}

这样就得到了JSON文件的数据。下一步是将数据转换成JSON,这需要使用JsonLib中的JsonLoadBuffer()函数:

  Json = JsonLoadBuffer (Data, FileSize, 0x4, &JsonError);if (NULL == Json) {DEBUG ((EFI_D_ERROR, "[%a][%d] Failed. - %r\n", __FUNCTION__, __LINE__, Status));goto DONE;}Print (L"JsonValueIsObject: %d\r\n", JsonValueIsObject (Json));Print (L"Json: %a\r\n", JsonDumpString (Json, EDKII_JSON_COMPACT));

测试得到的结果:

在这里插入图片描述

可以看到这里已经生成了BIOS下的JSON对象。如果想要得到其中具体的某一项:

  JsonData = JsonObjectGetValue (Json, "name");if (JsonValueIsString (JsonData)) {Print (L"Name: %a\r\n", JsonValueGetAsciiString (JsonData));}

这样就会打印name键对应的值:

在这里插入图片描述

除了读取键值,还可以通过键修改对应的值,比如这里的name:

  // Create new JSON object for string.NewData = JsonValueInitAsciiString ("JIANGWEI");if (NULL == NewData) {DEBUG ((EFI_D_ERROR, "[%a][%d] Failed. - %r\n", __FUNCTION__, __LINE__, Status));goto DONE;}// Set JSON value.Status = JsonObjectSetValue (Json, "name", NewData);if (EFI_ERROR (Status)) {DEBUG ((EFI_D_ERROR, "[%a][%d] Failed. - %r\n", __FUNCTION__, __LINE__, Status));goto DONE;}

这里JSON对象就被修改了。如果想要将修改的值保存到文件,目前的JsonLib中似乎没有对应的函数,不过还是可以通过一些处理将数据写入文件:

  FileSize = AsciiStrLen (NewJson);FileData = AllocateZeroPool (FileSize + 2);CopyMem (FileData, JsonDumpString (Json, EDKII_JSON_ENSURE_ASCII), FileSize);FileData[FileSize] = 0xD;FileData[FileSize + 1] = 0xA;FileSize = FileSize + 2;BeniDumpHex (2, 0, FileSize, FileData);Status = ShellWriteFile (FileHandle, &FileSize, FileData);

这里是将字符串转换成了文件内容然后写入文件,区别是字符串以’\0’结尾,而文件最后是换行符(似乎不太对?)。

相关内容

热门资讯

AI做攻略、“双向奔赴”……国... 本文转自:人民网人民网记者 许维娜今年国庆假期,AI(人工智能)成了不少年轻人的“旅行搭子”。行前做...
合肥的这个“梗”, 翻篇了 社交平台的评论区,曾长期流传一句专属于合肥的黑色幽默。有人问合肥哪里好玩,本地网友半开玩笑地回复:合...
7万+旅游中高层都在的群,今天... 做旅游这行,资源卡位、渠道互通、项目落地——往往就差一个“对的机会”。我们的行业社群已聚集70,00...
一场帐篷音乐节,如何让井研从“... 帐篷音乐节现场封面新闻记者 周洪攀10月的研溪湿地,晚风里裹着柑橘的清甜与民谣的回响。夜幕降临,10...
白鹤翩翩落星愿,上海迪士尼度假... 10月9日,世界候鸟日前夕,上海迪士尼度假区星愿公园的湖风里多了一分白鹤的灵动。三座白鹤雕塑正式揭幕...
成都锦江边赏初秋枫叶飘飘 目前,成都锦江边国华街枫叶树红了。近年来,国华街附近的几条街都栽种了红枫树,是城区较集中看枫叶的点位...
GBTA:商务旅行正在复苏,但... 亚太正在成为全球商务旅行增长的重要引擎。在经历疫情后的快速反弹之后,全球商务旅行正在进入一个新的增长...
从景区焕新到节赛引流 邹城双节... 齐鲁网·闪电新闻10月9日讯 中秋、国庆“双节”假期,邹城市文化和旅游局提前谋划、周密部署,立足自身...
江山如此多娇 且看石楼今朝 金秋十月,黄河岸畔秋意盎然,丰收盛会喜迎国庆。本次石楼国庆文旅活动以“江山如此多娇,且看石楼今朝”为...
海南国庆假期接待游客475.4... 2026年国庆假期,海南接待游客475.40万人次,较2025年增长13.1%,较2024年增长15...