日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

x58添加uefi_在看UEFI CODE

發布時間:2023/12/29 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 x58添加uefi_在看UEFI CODE 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

efi code里面有關于init 8259的code,也就是legacy8259protocol的實作

對8259的編程,我們是對其相應端口發送ICW(初始化命令字)來完成的,

總共需要發送4個ICW,而且必須按次序發送,這里提一下8259a編程的一些東西,2片8259a級連,一個為主片,一個為從片,從片的INT端口與主片的IRQ2相連,主片的訪問端口為0x20和0x21,從片為0xa和0xa1

在legacy bios中IRQ0-IRQ7被分配了0x8-0xf的中斷矢量(中斷號),

IRQ-8-IRQF

被分配為0x70-0x78,這也可以看做是實模式下是這樣來分的,但當cpu轉到保護模式的時候,中斷號0x8-0xf都被cpu用來處理錯誤了,所以我們必須從新對8259進行編程,設置中斷號的起始地址,

EFI_LEGACY_8259_PROTOCOL 中的SetVectorBase就是干這種事情的,

從字面的意思也可以看出來,“設置中斷矢量的基地址”

在EFI BIOS中我們將master interrupt base 設置為0x58,slave interr

base設置為0x70,linux中我們是將master interrupt base設置0xf0,slave設置為0xf8

設置這些base address的時候,我們就要對8259進行編程,也就是要發四個ICW了

EFI_STATUS SetVectorBase(

IN

EFI_LEGACY_8259_PROTOCOL?*This,

IN UINT8

MasterBase,

IN UINT8

SlaveBase

)

{

//8259 Master

if (MasterBase != gMasterBase)

{

IoWrite8(0x20,ICW1);?//Start

8259 Master Initialization.

IoWrite8(0x21,MasterBase);?//Set

Interrupt Offset

IoWrite8(0x21,ICW3_M);?//Set

Slave IRQ.

IoWrite8(0x21,ICW4);?//Set

8259 mode. See ICW4 comments with #define.

gMasterBase = MasterBase;

}

//8259 Slave

if (SlaveBase != gSlaveBase)

{

IoWrite8(0xa0,ICW1);?//Start

8259 Slave?Initialization.

IoWrite8(0xa1,SlaveBase);?//Set

Interrupt Offset

IoWrite8(0xa1,ICW3_S);?//Set

Slave IRQ.

IoWrite8(0xa1,ICW4);?//Set

8259 mode. See ICW4 comments with #define.

gSlaveBase = SlaveBase;

}

return EFI_SUCCESS;

}

ICW1:發送到0x20(主片)及0xa0(從片)端口

7 6 5 4 3 2 1 0

0 0 0 1 M 0 C I

I 位:若置位,表示ICW4 會被發送。(ICW4 等下解釋)

C 位:若清零,表示工作在級聯環境下。

M 位:指出中斷請求的電平觸發模式,在PC 機中,它應當被置零,表示采用“邊沿觸發模

式”。

ICW2:發送到0x21(主片)及0xa1(從片)端口

7 6 5 4 3 2 1 0

A7 A6 A5 A4 A3 0 0 0

ICW2 用來指示出IRQ0 使用的中斷號是什么,因為最后三位均是零,因此要求IRQ0 的中

斷號必須是8,的倍數,這又是一個很巧妙的設計。因為IRQ1 的中斷號就是IRQ0 的中斷

號+1,IRQ2 的中斷號就是IRQ0 的中斷號+2,……,IRQ7 的中斷號就是IRQ0 的中斷號+1,

剛好填滿一個8 個的中斷向量號空間。

ICW3:發送到0x21(主片)及0xa1(從片)端口

ICW3 只有在級聯工作的時候才會被發送,它主要用來建立兩處PIC 之間的連接,對于主片

與從片,它結構是不一樣的。

(主片結構:)

7 6 5 4 3 2 1 0

IRQ7 IRQ6 IRQ5 IRQ4 IRQ3 IRQ2 IRQ1 IRQ0

上面,如果相應的位被置1,則相應的IRQ 線就被用于與從片連接,若清零則表示被連接到

外圍設備。

(從片結構:)

7 6 5 4 3 2 1 0

0 0 0 0 0 IRQ

IRQ 位指出了是主片的哪一個IRQ 連到了從片,這需要同主片上發送的上面的主片結構字

一致。

ICW4:發送到0x21(主片)及0xa1(從片)端口

7 6 5 4 3 2 1 0

0 0 0 0 0 0 EOI 80x86

80x86 位:若置位表示工作在80x86 架構下。

EOI 位:若置位表示自動結束,在PC 上這位需要被清零。

在EFI BIOS code中的定義為

#define

ICW1?0x11

#define

ICW3_M?1<<2

#define

ICW3_S?2

#define

ICW4?1

與上面的說明是一致的

EFI_LEGACY_8259_PROTOCOL中SetMode這個function,是設置現在的8259處于實模式還是處于保護模式下,要中斷屏蔽那些IRQ,中斷觸發的方式是什么樣的(邊沿還是水平)

其中這個會用到2個全局變量

UINT16?gIrqMask[2]?=

{0xffff,0xffff};?UINT16?gIrqTrigger[2]?=

{0,0};?一個是控制中斷屏蔽regisgter的,一個是控制中斷觸發的方式,數組為2,一個用于real

mode,一個用于protect mode

看一下setmode的函數實作

EFI_STATUS SetMode(

IN

EFI_LEGACY_8259_PROTOCOL?*This,

IN

EFI_8259_MODE?Mode,

IN UINT16

*Mask

OPTIONAL,

IN

UINT16?*EdgeLevel?OPTIONAL

)

{

if (Mode >= Efi8259MaxMode) return

EFI_INVALID_PARAMETER;

gMode = Mode;

if (Mask) gIrqMask[Mode] = *Mask;

if (EdgeLevel) gIrqTrigger[Mode] =

*EdgeLevel;

ProgramIrqMaskTrigger();

return EFI_SUCCESS;

}

可以猜想?ProgramIrqMaskTrigger()就是操作8259

register的函數

VOID ProgramIrqMaskTrigger()

{

IoWrite8(0x21,(UINT8)gIrqMask[gMode]);

IoWrite8(0xa1,(UINT8)(gIrqMask[gMode]>>8));

//

// 4d0 can not be accessed as by IoWrite16, we

have to split

//

IoWrite8(0x4d0,(UINT8)gIrqTrigger[gMode]);

IoWrite8(0x4d1,(UINT8)(gIrqTrigger[gMode]>>8));

}

其中

IoWrite8(0x21,(UINT8)gIrqMask[gMode]);

IoWrite8(0xa1,(UINT8)(gIrqMask[gMode]>>8));

為操作8259a OCW命令register

OCW1:中斷屏蔽,發送到0x21(主片)或0xa1(從片)端口

7 6 5 4 3 2 1 0

IRQ7 IRQ6 IRQ5 IRQ4 IRQ3 IRQ2 IRQ1 IRQ0

如果相應的位置1,則表示屏蔽相應的IRQ 請求。

EFI_LEGACY_8259_PROTOCOL中GetMask和SetMask,也是操作mask和trigger的,原理和以上相同

GetVector字面意思,得到中斷號,也就是上面說的我們設置IRQ0對應的中斷號為0x58,我們現在要得到這個0x58,就靠這個函數了,無非就是倒過來運算而已

Master的IRQ對應得中斷好號為IRQ+masterbase

Slave上的IRQ為IRQ+slavebase-8 而已

EnableIRQ() DisableIRQ()這些函數的都是操作OCW1

GetInterruptLine()為讀配置空間,得到IRQ編號

EndOfInterrupt()在中斷處理函數里面發送EOI命令

如果 EOI 被設為自動的,那么ISR 中的位總是被清零的(在EOI 被置位的情況下,8259A

只要向CPU 發送了中斷號就會將ISR 中的相應位清零),也就是如果有中斷來,芯片就會馬

上再向CPU 發出中斷請求,即使CPU 正在處理IRQ0 的中斷,CPU 并不知道誰的優先級高,

它只會簡單的響應8259A 送來的中斷,因此,這種情況下低優先級的中斷就可能會中斷高

優先級的中斷服務程序。所以在PC 中,我們總是將EOI 位清零,而在中斷服務程序結束的

時候才發送EOI 消息。

注意一點,發EOI命令的時候,先發送給從片,再發送給主片

總結

以上是生活随笔為你收集整理的x58添加uefi_在看UEFI CODE的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。