# EDID 介紹
EDID全名為Extended Display Identification Data,是由VESA協會制定的顯示器標準資訊格式。具體來說,可以把 EDID 當成一個顯示器的 metadata / 身分證,其內容會包含顯示器的相關資訊,如顯示器名稱、產品序號、支援解析度、聲音格式等等。目的為告訴輸出端顯示器支援的能力,確保電腦或是機上盒等影音輸出裝置,在連接上顯示器後,能根據資訊輸出正確的影音格式,因此可以避免無法顯示或顯示比例不正常等狀況發生。
目前此項技術已廣泛應用於影音顯示介面如 DisplayPort、HDMI。在實作上,為了要容納先前提到的EDID資訊於顯示器中,儲存在 EEPROM 中,並且在HDMI介面會利用I2C的介面來進行雙向的資料傳輸。
EDID 透過 I2C 與 source 進行傳輸


目前 HDMI 介面使用 EDID v1.3,DP 介面則使用 EDID v1.4
## EDID 資料結構(v1.3)
EDID 由 1 ~ 4 個 block 組成,每個 block 大小為 128 Byte。第一個 block 又稱為 EDID Base Block,由 VESA EDID 標準制定。隨著越來越多的顯示/聲音格式,需要更多的容量存放訊息,所以也發展成利用 Extension Block 格式在 EDID 內放置多個 Block,最多可放置 255個 Block。
EDID Base Block 又稱為 Block,每個 Byte 採用 16 進位資料格式。
TODO:
write the detail of the first block
## UEFI EDID related protocol
在 UEFI 環境下,常會需要透過 GOP 與其相關的 Protocol 進行顯示相關功能開發,而 UEFI 定義了相關的 protocol 來取得 EDID 資訊
### EdidDiscovered
```c!
typedef struct {
UINT32 SizeOfEdid;
UINT8 *Edid;
} EFI_EDID_DISCOVERED_PROTOCOL;
```
#### SizeofEdid:
Edid buffer 大小,最小值 128 byte。
若沒有 EDID 資訊,則設為 0。
#### Edid
指向唯讀位元陣列的指標,該位元陣列為顯示器(video output device) EDID 資訊。
#### 說明
該 Protocol 包含從顯示器回傳的 EDID 資訊,若該顯示器沒有任何 EDID 資訊,則 SizeofEdid = 0 且 \*Edid = NULL;
當 GOPDriverBinding -> Start() 被呼叫時,該 Protocol 會被 installed 在每個實體連接的 display device 的 child handle 上
Ex: 當一個 HDMI display device 連接到 video controller 時,HDMI ddevice 會被 installed 成一個 child handle,並同時 install EdidDiscovered.
若連接著 video output device 並非 EDID capable(非常老的類比 CRT 螢幕),或是 EDID 資訊無法取得,則該 protocol 會以 SizeofEdid = 0 且 \*Edid = NULL 的方式被安裝。
### EdidOverride
```c!
typedef struct _EFI_EDID_OVERRIDE_PROTOCOL {
EFI_EDID_OVERRIDE_PROTOCOL_GET_EDID GetEdid;
} EFI_EDID_OVERRIDE_PROTOCOL;
```
#### GetEdid
回傳 EDID value & attribute
#### 說明
由 platform firmware 產生,該 protocol 允許系統提供另一個 EDID 資訊給 GOP。
#### EFI_EDID_OVERRIDE_PROTOCOL.GetEdid()
```c
typedef
EFI_STATUS
(EFIAPI \*EFI_EDID_OVERRIDE_PROTOCOL_GET_EDID) (
IN EFI_EDID_OVERRIDE_PROTOCOL *This,
IN EFI_HANDLE *ChildHandle,
OUT UINT32 *Attributes,
OUT UINTN *EdidSize,
OUT UINT8 **Edid
);
```
#### 說明
Returns policy information and potentially a replacement EDID for the specified video output device.
This protocol is optionally provided by the platform to override or provide EDID information and/or output device display properties to the producer of the Graphics Output protocol. If ChildHandle does not represent a video output device, or there are no override for the video output device specified by ChildHandle, then EFI_UNSUPPORTED is returned. Otherwise, the Attributes, EdidSize, and Edid parameters are returned along with a status of EFI_SUCCESS.
### EdidActive
```c!
typedef struct {
UINT32 SizeOfEdid;
UINT8 *Edid;
} EFI_EDID_ACTIVE_PROTOCOL;
```
#### 說明:
包含 **正在使用**的(Active)顯示器的 EDID 資訊,
該資訊由 EFI_EDID_OVERRIDE_PROTOCOL 或 EFI_EDID_DISCOVERED_PROTOCOL 提供。
若沒有 override,則 EDID 資訊和 EFI_EDID_DISCOVERED_PROTOCOL 相同
When the set of active video output devices attached to a frame buffer are selected, the EFI_EDID_ACTIVE_PROTOCOL must be installed onto the handles that represent the each of those active video output devices. If the EFI_EDID_OVERRIDE_PROTOCOL has override EDID information for an active video output device, then the EDID information specified by GetEdid() is used for the EFI_EDID_ACTIVE_PROTOCOL. Otherwise, the EDID information from the EFI_EDID_DISCOVERED_PROTOCOL is used for the EFI_EDID_ACTIVE_PROTOCOL. Since all EDID information is read-only, it is legal for the pointer associated with the EFI_EDID_ACTIVE_PROTOCOL to be the same as the pointer associated with the EFI_EDID_DISCOVERED_PROTOCOL when no overrides are present.
## UEFI Application 取得 EDID 資訊
下列程式為一個 UEFI application,透過 EdidDiscoveredProtocol 取得 EDID 資訊。
```c
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/EdidDiscovered.h>
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_EDID_DISCOVERED_PROTOCOL *EdidDiscovered;
// Locate the EDID Discovered Protocol.
Status = gBS->LocateProtocol(&gEfiEdidDiscoveredProtocolGuid, NULL, (VOID **)&EdidDiscovered);
if (EFI_ERROR(Status)) {
Print(L"Failed to locate EDID Discovered Protocol: %r\n", Status);
return Status;
}
// Check if EDID data is available.
if (EdidDiscovered->Edid == NULL || EdidDiscovered->SizeOfEdid == 0) {
Print(L"No EDID data available.\n");
return EFI_NOT_FOUND;
}
// Print the EDID data in hexadecimal format.
Print(L"EDID Data (%d bytes):\n", EdidDiscovered->SizeOfEdid);
for (UINTN i = 0; i < EdidDiscovered->SizeOfEdid; i++) {
Print(L"%02x ", EdidDiscovered->Edid[i]);
if ((i + 1) % 16 == 0) {
Print(L"\n");
}
}
Print(L"\n");
return EFI_SUCCESS;
}
```
## Reference
https://www.graniteriverlabs.com/zh-tw/technical-blog/edid-overview
https://silverwind1982.pixnet.net/blog/post/365351044
https://uefi.org/sites/default/files/resources/2_-_AMD_UEFI_Plugfest_EDID_Spring2012.pdf
https://glenwing.github.io/docs/VESA-EEDID-A1.pdf