Compare commits
No commits in common. "main" and "master" have entirely different histories.
8899 changed files with 125580 additions and 763362 deletions
|
|
@ -1,6 +1,3 @@
|
||||||
# Override checkpatch's default max line length 100
|
|
||||||
--max-line-length=96
|
|
||||||
|
|
||||||
# Not Linux, so don't expect a Linux tree.
|
# Not Linux, so don't expect a Linux tree.
|
||||||
--no-tree
|
--no-tree
|
||||||
|
|
||||||
|
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -35,7 +35,6 @@ tags
|
||||||
.cache
|
.cache
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
.vscode/
|
.vscode/
|
||||||
.clangd
|
|
||||||
|
|
||||||
# Cross-compile toolkits
|
# Cross-compile toolkits
|
||||||
xgcc/
|
xgcc/
|
||||||
|
|
|
||||||
51
.gitmodules
vendored
51
.gitmodules
vendored
|
|
@ -1,81 +1,70 @@
|
||||||
[submodule "3rdparty/blobs"]
|
[submodule "3rdparty/blobs"]
|
||||||
path = 3rdparty/blobs
|
path = 3rdparty/blobs
|
||||||
url = https://review.coreboot.org/blobs.git
|
url = ../blobs.git
|
||||||
update = none
|
update = none
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
[submodule "util/nvidia-cbootimage"]
|
[submodule "util/nvidia-cbootimage"]
|
||||||
path = util/nvidia/cbootimage
|
path = util/nvidia/cbootimage
|
||||||
url = https://review.coreboot.org/nvidia-cbootimage.git
|
url = ../nvidia-cbootimage.git
|
||||||
[submodule "vboot"]
|
[submodule "vboot"]
|
||||||
path = 3rdparty/vboot
|
path = 3rdparty/vboot
|
||||||
url = https://review.coreboot.org/vboot.git
|
url = ../vboot.git
|
||||||
branch = main
|
branch = main
|
||||||
[submodule "arm-trusted-firmware"]
|
[submodule "arm-trusted-firmware"]
|
||||||
path = 3rdparty/arm-trusted-firmware
|
path = 3rdparty/arm-trusted-firmware
|
||||||
url = https://review.coreboot.org/arm-trusted-firmware.git
|
url = ../arm-trusted-firmware.git
|
||||||
|
[submodule "3rdparty/chromeec"]
|
||||||
|
path = 3rdparty/chromeec
|
||||||
|
url = ../chrome-ec.git
|
||||||
[submodule "libhwbase"]
|
[submodule "libhwbase"]
|
||||||
path = 3rdparty/libhwbase
|
path = 3rdparty/libhwbase
|
||||||
url = https://review.coreboot.org/libhwbase.git
|
url = ../libhwbase.git
|
||||||
[submodule "libgfxinit"]
|
[submodule "libgfxinit"]
|
||||||
path = 3rdparty/libgfxinit
|
path = 3rdparty/libgfxinit
|
||||||
url = https://review.coreboot.org/libgfxinit.git
|
url = ../libgfxinit.git
|
||||||
[submodule "3rdparty/fsp"]
|
[submodule "3rdparty/fsp"]
|
||||||
path = 3rdparty/fsp
|
path = 3rdparty/fsp
|
||||||
url = https://review.coreboot.org/fsp.git
|
url = ../fsp.git
|
||||||
update = none
|
update = none
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
[submodule "opensbi"]
|
[submodule "opensbi"]
|
||||||
path = 3rdparty/opensbi
|
path = 3rdparty/opensbi
|
||||||
url = https://review.coreboot.org/opensbi.git
|
url = ../opensbi.git
|
||||||
[submodule "intel-microcode"]
|
[submodule "intel-microcode"]
|
||||||
path = 3rdparty/intel-microcode
|
path = 3rdparty/intel-microcode
|
||||||
url = https://review.coreboot.org/intel-microcode.git
|
url = ../intel-microcode.git
|
||||||
update = none
|
update = none
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
branch = main
|
branch = main
|
||||||
[submodule "3rdparty/ffs"]
|
[submodule "3rdparty/ffs"]
|
||||||
path = 3rdparty/ffs
|
path = 3rdparty/ffs
|
||||||
url = https://review.coreboot.org/ffs.git
|
url = ../ffs.git
|
||||||
[submodule "3rdparty/amd_blobs"]
|
[submodule "3rdparty/amd_blobs"]
|
||||||
path = 3rdparty/amd_blobs
|
path = 3rdparty/amd_blobs
|
||||||
url = https://review.coreboot.org/amd_blobs
|
url = ../amd_blobs
|
||||||
update = none
|
update = none
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
[submodule "3rdparty/cmocka"]
|
[submodule "3rdparty/cmocka"]
|
||||||
path = 3rdparty/cmocka
|
path = 3rdparty/cmocka
|
||||||
url = https://review.coreboot.org/cmocka.git
|
url = ../cmocka.git
|
||||||
update = none
|
update = none
|
||||||
branch = stable-1.1
|
branch = stable-1.1
|
||||||
[submodule "3rdparty/qc_blobs"]
|
[submodule "3rdparty/qc_blobs"]
|
||||||
path = 3rdparty/qc_blobs
|
path = 3rdparty/qc_blobs
|
||||||
url = https://review.coreboot.org/qc_blobs.git
|
url = ../qc_blobs.git
|
||||||
update = none
|
update = none
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
[submodule "3rdparty/intel-sec-tools"]
|
[submodule "3rdparty/intel-sec-tools"]
|
||||||
path = 3rdparty/intel-sec-tools
|
path = 3rdparty/intel-sec-tools
|
||||||
url = https://review.coreboot.org/9esec-security-tooling.git
|
url = ../9esec-security-tooling.git
|
||||||
ignore = dirty
|
|
||||||
[submodule "3rdparty/stm"]
|
[submodule "3rdparty/stm"]
|
||||||
path = 3rdparty/stm
|
path = 3rdparty/stm
|
||||||
url = https://review.coreboot.org/STM
|
url = ../STM
|
||||||
branch = stmpe
|
branch = stmpe
|
||||||
[submodule "util/goswid"]
|
[submodule "util/goswid"]
|
||||||
path = util/goswid
|
path = util/goswid
|
||||||
url = https://review.coreboot.org/goswid
|
url = ../goswid
|
||||||
branch = trunk
|
branch = trunk
|
||||||
ignore = dirty
|
|
||||||
[submodule "src/vendorcode/amd/opensil/genoa_poc/opensil"]
|
[submodule "src/vendorcode/amd/opensil/genoa_poc/opensil"]
|
||||||
path = src/vendorcode/amd/opensil/genoa_poc/opensil
|
path = src/vendorcode/amd/opensil/genoa_poc/opensil
|
||||||
url = https://review.coreboot.org/opensil_genoa_poc.git
|
url = ../opensil_genoa_poc.git
|
||||||
[submodule "3rdparty/open-power-signing-utils"]
|
|
||||||
path = 3rdparty/open-power-signing-utils
|
|
||||||
url = https://review.coreboot.org/open-power-signing-utils.git
|
|
||||||
[submodule "src/vendorcode/amd/opensil/phoenix_poc/opensil"]
|
|
||||||
path = src/vendorcode/amd/opensil/phoenix_poc/opensil
|
|
||||||
url = https://github.com/openSIL/openSIL.git
|
|
||||||
branch = phoenix_poc
|
|
||||||
[submodule "src/vendorcode/amd/opensil/turin_poc/opensil"]
|
|
||||||
path = src/vendorcode/amd/opensil/turin_poc/opensil
|
|
||||||
url = https://github.com/openSIL/openSIL.git
|
|
||||||
branch = turin_poc
|
|
||||||
|
|
||||||
|
|
|
||||||
2
3rdparty/amd_blobs
vendored
2
3rdparty/amd_blobs
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit aa9288a33c6d7a67e55b8757390029207593fa9f
|
Subproject commit 64cdd7c8ef199f5d79be14e7972fb7316f41beed
|
||||||
2
3rdparty/arm-trusted-firmware
vendored
2
3rdparty/arm-trusted-firmware
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 9109143417b24337d39a2a9583828a44996f8aac
|
Subproject commit 17bef2248d4547242463e27cfe48ec96029626b4
|
||||||
2
3rdparty/blobs
vendored
2
3rdparty/blobs
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 4a8de0324e7d389454ec33cdf66939b653bf6800
|
Subproject commit a8db7dfe823def043368857b8fbfbba86f2e9e47
|
||||||
1
3rdparty/chromeec
vendored
Submodule
1
3rdparty/chromeec
vendored
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit e486b388a73f1e19f3142774d0b3ee166e8f41ff
|
||||||
2
3rdparty/fsp
vendored
2
3rdparty/fsp
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 81399b3b61479abc379c2d01362d4b6dc6f515c9
|
Subproject commit dd98487fdef49068cf0df5e88ea886c1884ef510
|
||||||
2
3rdparty/intel-microcode
vendored
2
3rdparty/intel-microcode
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 250941fb670645d7d91f761cc63656ad3a1ec367
|
Subproject commit ece0d294a29a1375397941a4e6f2f7217910bc89
|
||||||
2
3rdparty/libgfxinit
vendored
2
3rdparty/libgfxinit
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3c3828add50024e90e57d6fbe0e660d1b66302d9
|
Subproject commit a4be8a21b0e2c752da0042c79aae5942418f53e2
|
||||||
1
3rdparty/open-power-signing-utils
vendored
1
3rdparty/open-power-signing-utils
vendored
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 591c8f53482243626901e1cc8a4ae321f314040d
|
|
||||||
2
3rdparty/qc_blobs
vendored
2
3rdparty/qc_blobs
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 6379308814bd00a8b6e36a4715bdb86ba019a3a7
|
Subproject commit a252198ec6544e13904cfe831cec3e784aaa715d
|
||||||
2
3rdparty/vboot
vendored
2
3rdparty/vboot
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 5c360ef458b0a013d8a6d47724bb0fffb5accbcf
|
Subproject commit 09fcd2184f9c714829503e84b8a7dfe7f2584e00
|
||||||
131
AUTHORS
131
AUTHORS
|
|
@ -15,14 +15,12 @@ Aaron Durbin
|
||||||
Abe Levkoy
|
Abe Levkoy
|
||||||
Abel Briggs
|
Abel Briggs
|
||||||
Abhinav Hardikar
|
Abhinav Hardikar
|
||||||
Abhishek Pandit-Subedi
|
|
||||||
AdaCore
|
AdaCore
|
||||||
Adam Liu
|
Adam Liu
|
||||||
Adam Mills
|
Adam Mills
|
||||||
Advanced Computing Lab, LANL
|
Advanced Computing Lab, LANL
|
||||||
Advanced Micro Devices, Inc.
|
Advanced Micro Devices, Inc.
|
||||||
AG Electronics Ltd.
|
AG Electronics Ltd.
|
||||||
Agogo
|
|
||||||
Ahamed Husni
|
Ahamed Husni
|
||||||
Akshu Agrawal
|
Akshu Agrawal
|
||||||
Al Hirani
|
Al Hirani
|
||||||
|
|
@ -41,42 +39,32 @@ Alexandru Gagniuc
|
||||||
Alexey Buyanov
|
Alexey Buyanov
|
||||||
Alexey Vazhnov
|
Alexey Vazhnov
|
||||||
Alice Sell
|
Alice Sell
|
||||||
Alicja Michalska
|
|
||||||
Allen-KH Cheng
|
Allen-KH Cheng
|
||||||
Alok Agarwal
|
|
||||||
Alper Nebi Yasak
|
|
||||||
Amanda Hwang
|
Amanda Hwang
|
||||||
American Megatrends International, LLC
|
American Megatrends International, LLC
|
||||||
Amersel
|
Amersel
|
||||||
Amit Caleechurn
|
Amit Caleechurn
|
||||||
Ana Carolina Cabral
|
|
||||||
Analog Devices Inc.
|
Analog Devices Inc.
|
||||||
Analogix Semiconductor
|
Analogix Semiconductor
|
||||||
Anand Mistry
|
Anand Mistry
|
||||||
Anand Vaikar
|
Anand Vaikar
|
||||||
Anastasios Koutian
|
|
||||||
Andre
|
|
||||||
Andre Heider
|
Andre Heider
|
||||||
Andrew McRae
|
Andrew McRae
|
||||||
Andrew SH Cheng
|
Andrew SH Cheng
|
||||||
Andrey Pronin
|
Andrey Pronin
|
||||||
Andriy Gapon
|
Andriy Gapon
|
||||||
Andy
|
|
||||||
Andy Fleming
|
Andy Fleming
|
||||||
Andy Pont
|
Andy Pont
|
||||||
Andy-ld Lu
|
Andy-ld Lu
|
||||||
Angel Pons
|
Angel Pons
|
||||||
Angela Czubak
|
|
||||||
Anil Kumar K
|
Anil Kumar K
|
||||||
Anna Karaś
|
Anna Karaś
|
||||||
Annie Chen
|
Annie Chen
|
||||||
Anton Kochkov
|
Anton Kochkov
|
||||||
Ao Zhong
|
Ao Zhong
|
||||||
Appukuttan V K
|
|
||||||
Arashk Mahshidfar
|
Arashk Mahshidfar
|
||||||
Arec Kao
|
Arec Kao
|
||||||
Ariel Fang
|
Ariel Fang
|
||||||
Ariel Otilibili
|
|
||||||
ARM Limited and Contributors
|
ARM Limited and Contributors
|
||||||
Arthur Heymans
|
Arthur Heymans
|
||||||
Asami Doi
|
Asami Doi
|
||||||
|
|
@ -86,12 +74,9 @@ Ashqti
|
||||||
ASPEED Technology Inc.
|
ASPEED Technology Inc.
|
||||||
Atheros Corporation
|
Atheros Corporation
|
||||||
Atmel Corporation
|
Atmel Corporation
|
||||||
Avi Uday
|
|
||||||
Avinash Munduru
|
|
||||||
Balaji Manigandan
|
Balaji Manigandan
|
||||||
Balázs Vinarz
|
Balázs Vinarz
|
||||||
BAP - Bruhnspace Advanced Projects
|
BAP - Bruhnspace Advanced Projects
|
||||||
Bartłomiej Grzesik
|
|
||||||
Baruch Siach
|
Baruch Siach
|
||||||
Ben Chuang
|
Ben Chuang
|
||||||
Ben Kao
|
Ben Kao
|
||||||
|
|
@ -102,26 +87,20 @@ Bernardo Perez Priego
|
||||||
Bhanu Prakash Maiya
|
Bhanu Prakash Maiya
|
||||||
Bill Xie
|
Bill Xie
|
||||||
Bin Meng
|
Bin Meng
|
||||||
Bincai Liu
|
|
||||||
Bitland Tech Inc.
|
Bitland Tech Inc.
|
||||||
Bob Moragues
|
Bob Moragues
|
||||||
Bora Guvendik
|
Bora Guvendik
|
||||||
Boris Barbulovski
|
Boris Barbulovski
|
||||||
Boris Mittelberg
|
Boris Mittelberg
|
||||||
Brandon Breitenstein
|
Brandon Breitenstein
|
||||||
Brandon Weeks
|
|
||||||
Brian Hsu
|
|
||||||
Brian Norris
|
Brian Norris
|
||||||
Bryant Ou
|
Bryant Ou
|
||||||
Carl-Daniel Hailfinger
|
Carl-Daniel Hailfinger
|
||||||
Carlos López
|
|
||||||
Casper Chang
|
Casper Chang
|
||||||
Cathy Xu
|
|
||||||
Caveh Jalali
|
Caveh Jalali
|
||||||
Cavium Inc.
|
Cavium Inc.
|
||||||
Chao Gui
|
Chao Gui
|
||||||
Chen-Tsung Hsieh
|
Chen-Tsung Hsieh
|
||||||
Chen. Gang C
|
|
||||||
Chia-Ling Hou
|
Chia-Ling Hou
|
||||||
Chien-Chih Tseng
|
Chien-Chih Tseng
|
||||||
Chris Wang
|
Chris Wang
|
||||||
|
|
@ -141,7 +120,6 @@ Cong Yang
|
||||||
CoolStar
|
CoolStar
|
||||||
coresystems GmbH
|
coresystems GmbH
|
||||||
Corey Osgood
|
Corey Osgood
|
||||||
Crystal Guo
|
|
||||||
Curt Brune
|
Curt Brune
|
||||||
Curtis Chen
|
Curtis Chen
|
||||||
Custom Ideas
|
Custom Ideas
|
||||||
|
|
@ -150,7 +128,6 @@ Da Lao
|
||||||
Daisuke Nojiri
|
Daisuke Nojiri
|
||||||
Damien Zammit
|
Damien Zammit
|
||||||
Dan Callaghan
|
Dan Callaghan
|
||||||
Dan Campbell
|
|
||||||
Daniel Campello
|
Daniel Campello
|
||||||
Daniel Gröber
|
Daniel Gröber
|
||||||
Daniel Kang
|
Daniel Kang
|
||||||
|
|
@ -161,7 +138,6 @@ Dave Airlie
|
||||||
David Brownell
|
David Brownell
|
||||||
David Greenman
|
David Greenman
|
||||||
David Hendricks
|
David Hendricks
|
||||||
David Li
|
|
||||||
David Lin
|
David Lin
|
||||||
David Milosevic
|
David Milosevic
|
||||||
David Mosberger-Tang
|
David Mosberger-Tang
|
||||||
|
|
@ -171,7 +147,6 @@ David Wu
|
||||||
Dawei Chien
|
Dawei Chien
|
||||||
Deepika Punyamurtula
|
Deepika Punyamurtula
|
||||||
Deepti Deshatty
|
Deepti Deshatty
|
||||||
Dehui Sun
|
|
||||||
Denis 'GNUtoo' Carikli
|
Denis 'GNUtoo' Carikli
|
||||||
Denis Dowling
|
Denis Dowling
|
||||||
DENX Software Engineering
|
DENX Software Engineering
|
||||||
|
|
@ -185,7 +160,6 @@ Divya S Sasidharan
|
||||||
Dmitry Ponamorev
|
Dmitry Ponamorev
|
||||||
Dmitry Torokhov
|
Dmitry Torokhov
|
||||||
DMP Electronics Inc.
|
DMP Electronics Inc.
|
||||||
Dolan Liu
|
|
||||||
Dominik Behr
|
Dominik Behr
|
||||||
Donghwa Lee
|
Donghwa Lee
|
||||||
Drew Eckhardt
|
Drew Eckhardt
|
||||||
|
|
@ -206,10 +180,7 @@ ELSOFT AG
|
||||||
Eltan B.V
|
Eltan B.V
|
||||||
Eltan B.V.
|
Eltan B.V.
|
||||||
Elyes Haouas
|
Elyes Haouas
|
||||||
Emilie Roberts
|
|
||||||
Enzo Potenza
|
|
||||||
Eran Mitrani
|
Eran Mitrani
|
||||||
Eren Peng
|
|
||||||
Eric Biederman
|
Eric Biederman
|
||||||
Eric Lai
|
Eric Lai
|
||||||
Eric Peers
|
Eric Peers
|
||||||
|
|
@ -221,21 +192,15 @@ Ethan Tsao
|
||||||
Eugene Myers
|
Eugene Myers
|
||||||
Evan Green
|
Evan Green
|
||||||
Evgeny Zinoviev
|
Evgeny Zinoviev
|
||||||
Evie (Ivi) Ballou
|
|
||||||
Fabian Groffen
|
Fabian Groffen
|
||||||
Fabian Kunkel
|
Fabian Kunkel
|
||||||
Fabian Meyer
|
|
||||||
Fabio Aiuto
|
Fabio Aiuto
|
||||||
Fabrice Bellard
|
Fabrice Bellard
|
||||||
Facebook, Inc.
|
Facebook, Inc.
|
||||||
Federico Amedeo Izzo
|
|
||||||
Fei Yan
|
|
||||||
Felix Friedlander
|
Felix Friedlander
|
||||||
Felix Held
|
Felix Held
|
||||||
Felix Singer
|
Felix Singer
|
||||||
Fengquan Chen
|
Fengquan Chen
|
||||||
Filip Brozovic
|
|
||||||
Filip Lewiński
|
|
||||||
Flora Fu
|
Flora Fu
|
||||||
Florian Laufenböck
|
Florian Laufenböck
|
||||||
Francois Toguo Fotso
|
Francois Toguo Fotso
|
||||||
|
|
@ -250,12 +215,8 @@ Freescale Semiconductor, Inc.
|
||||||
Furquan Shaikh
|
Furquan Shaikh
|
||||||
Gaggery Tsai
|
Gaggery Tsai
|
||||||
Gang C Chen
|
Gang C Chen
|
||||||
Garen Wu
|
|
||||||
Gareth Yu
|
|
||||||
Garmin Chang
|
Garmin Chang
|
||||||
Gary Jennejohn
|
Gary Jennejohn
|
||||||
Gavin Liu
|
|
||||||
George Burgess
|
|
||||||
George Trudeau
|
George Trudeau
|
||||||
Gerald Van Baren
|
Gerald Van Baren
|
||||||
Gerd Hoffmann
|
Gerd Hoffmann
|
||||||
|
|
@ -263,7 +224,6 @@ Gergely Kiss
|
||||||
Google LLC
|
Google LLC
|
||||||
Greg Watson
|
Greg Watson
|
||||||
Grzegorz Bernacki
|
Grzegorz Bernacki
|
||||||
Guangjie Song
|
|
||||||
Guennadi Liakhovetski
|
Guennadi Liakhovetski
|
||||||
Guodong Liu
|
Guodong Liu
|
||||||
Gwendal Grignou
|
Gwendal Grignou
|
||||||
|
|
@ -271,21 +231,17 @@ Hal Martin
|
||||||
Hao Chou
|
Hao Chou
|
||||||
Hao Wang
|
Hao Wang
|
||||||
HardenedLinux
|
HardenedLinux
|
||||||
Harrie Paijmans
|
|
||||||
Harsha B R
|
Harsha B R
|
||||||
Harshit Sharma
|
Harshit Sharma
|
||||||
Henry C Chen
|
Henry C Chen
|
||||||
Herbert Wu
|
|
||||||
Hewlett Packard Enterprise Development LP
|
Hewlett Packard Enterprise Development LP
|
||||||
Hewlett-Packard Development Company, L.P.
|
Hewlett-Packard Development Company, L.P.
|
||||||
Himanshu Sahdev
|
Himanshu Sahdev
|
||||||
Hope Wang
|
|
||||||
Housong Zhang
|
Housong Zhang
|
||||||
Hsiao Chien Sung
|
Hsiao Chien Sung
|
||||||
Hsin-hsiung wang
|
Hsin-hsiung wang
|
||||||
Hsin-Te Yuan
|
Hsin-Te Yuan
|
||||||
Hsuan Ting Chen
|
Hsuan Ting Chen
|
||||||
Hualin Wei
|
|
||||||
Huaqin Technology Co., Ltd
|
Huaqin Technology Co., Ltd
|
||||||
Huaqin Telecom Inc.
|
Huaqin Telecom Inc.
|
||||||
Hui Liu
|
Hui Liu
|
||||||
|
|
@ -300,7 +256,6 @@ Igor Pavlov
|
||||||
Ikjoon Jang
|
Ikjoon Jang
|
||||||
Imagination Technologies
|
Imagination Technologies
|
||||||
Infineon Technologies
|
Infineon Technologies
|
||||||
Ingo Reitz
|
|
||||||
InKi Dae
|
InKi Dae
|
||||||
INSPUR Co., Ltd
|
INSPUR Co., Ltd
|
||||||
Intel Corporation
|
Intel Corporation
|
||||||
|
|
@ -318,14 +273,11 @@ Jakub Czapiga
|
||||||
James Chao
|
James Chao
|
||||||
James Lo
|
James Lo
|
||||||
James Ye
|
James Ye
|
||||||
Jameson Thies
|
|
||||||
Jamie Chen
|
Jamie Chen
|
||||||
Jamie Ryu
|
Jamie Ryu
|
||||||
Jan Dabros
|
Jan Dabros
|
||||||
Jan Philipp Groß
|
|
||||||
Jan Samek
|
Jan Samek
|
||||||
Jan Tatje
|
Jan Tatje
|
||||||
Jarried Lin
|
|
||||||
Jason Glenesk
|
Jason Glenesk
|
||||||
Jason Nein
|
Jason Nein
|
||||||
Jason V Le
|
Jason V Le
|
||||||
|
|
@ -334,9 +286,6 @@ Jason Zhao
|
||||||
jason-ch chen
|
jason-ch chen
|
||||||
Jason-jh Lin
|
Jason-jh Lin
|
||||||
Jay Patel
|
Jay Patel
|
||||||
Jayvik Desai
|
|
||||||
Jean Lucas
|
|
||||||
Jędrzej Ciupis
|
|
||||||
Jeff Chase
|
Jeff Chase
|
||||||
Jeff Daly
|
Jeff Daly
|
||||||
Jeff Li
|
Jeff Li
|
||||||
|
|
@ -357,12 +306,9 @@ Jingle Hsu
|
||||||
Jitao Shi
|
Jitao Shi
|
||||||
Joe Pillow
|
Joe Pillow
|
||||||
Joe Tessler
|
Joe Tessler
|
||||||
Joel Bueno
|
|
||||||
Joel Kitching
|
Joel Kitching
|
||||||
Joel Linn
|
|
||||||
Joey Peng
|
Joey Peng
|
||||||
Johanna Schander
|
Johanna Schander
|
||||||
Johannes Hahn
|
|
||||||
John Su
|
John Su
|
||||||
John Zhao
|
John Zhao
|
||||||
Johnny Li
|
Johnny Li
|
||||||
|
|
@ -379,10 +325,7 @@ Jordan Crouse
|
||||||
Jörg Mische
|
Jörg Mische
|
||||||
Joseph Smith
|
Joseph Smith
|
||||||
Josie Nordrum
|
Josie Nordrum
|
||||||
Juan José García-Castro Crespo
|
|
||||||
Julia Kittlinger
|
|
||||||
Julia Tsai
|
Julia Tsai
|
||||||
Julian Intronati
|
|
||||||
Julian Schroeder
|
Julian Schroeder
|
||||||
Julian Stecklina
|
Julian Stecklina
|
||||||
Julien Viard de Galbert
|
Julien Viard de Galbert
|
||||||
|
|
@ -391,12 +334,9 @@ Kacper Stojek
|
||||||
Kaiyen Chang
|
Kaiyen Chang
|
||||||
Kane Chen
|
Kane Chen
|
||||||
Kangheui Won
|
Kangheui Won
|
||||||
KangMin Wang
|
|
||||||
Kapil Porwal
|
Kapil Porwal
|
||||||
Karol Zmyslowski
|
Karol Zmyslowski
|
||||||
Karthik Ramasubramanian
|
Karthik Ramasubramanian
|
||||||
Ke Zheng
|
|
||||||
Kei Hiroyoshi
|
|
||||||
Keith Hui
|
Keith Hui
|
||||||
Keith Packard
|
Keith Packard
|
||||||
Kenneth Chan
|
Kenneth Chan
|
||||||
|
|
@ -407,12 +347,10 @@ Kevin Chowski
|
||||||
Kevin Cody-Little
|
Kevin Cody-Little
|
||||||
Kevin Keijzer
|
Kevin Keijzer
|
||||||
Kevin O'Connor
|
Kevin O'Connor
|
||||||
Kevin Yang
|
|
||||||
Kevin3 Yang
|
Kevin3 Yang
|
||||||
kewei xu
|
kewei xu
|
||||||
Kilari Raasi
|
Kilari Raasi
|
||||||
Kirk Wang
|
Kirk Wang
|
||||||
Kiwi Liu
|
|
||||||
Konrad Adamczyk
|
Konrad Adamczyk
|
||||||
Kontron Europe GmbH
|
Kontron Europe GmbH
|
||||||
Kornel Dulęba
|
Kornel Dulęba
|
||||||
|
|
@ -422,7 +360,6 @@ Kshitij
|
||||||
Kshitiz Godara
|
Kshitiz Godara
|
||||||
Kulkarni. Srinivas
|
Kulkarni. Srinivas
|
||||||
Kun Liu
|
Kun Liu
|
||||||
KunYi Chen
|
|
||||||
Kyle Lin
|
Kyle Lin
|
||||||
Kyösti Mälkki
|
Kyösti Mälkki
|
||||||
Lance Zhao
|
Lance Zhao
|
||||||
|
|
@ -430,11 +367,9 @@ Lawrence Chang
|
||||||
Leah Rowe
|
Leah Rowe
|
||||||
Lean Sheng Tan
|
Lean Sheng Tan
|
||||||
Lei Wen
|
Lei Wen
|
||||||
Lennart Eichhorn
|
|
||||||
Lenovo Group Ltd
|
Lenovo Group Ltd
|
||||||
Leo Chou
|
Leo Chou
|
||||||
Li-Ta Lo
|
Li-Ta Lo
|
||||||
Li1 Feng
|
|
||||||
Liam Flaherty
|
Liam Flaherty
|
||||||
Libra Li
|
Libra Li
|
||||||
Libretrend LDA
|
Libretrend LDA
|
||||||
|
|
@ -445,15 +380,10 @@ linear
|
||||||
Linus Torvalds
|
Linus Torvalds
|
||||||
Linux Networx, Inc.
|
Linux Networx, Inc.
|
||||||
LiPPERT ADLINK Technology GmbH
|
LiPPERT ADLINK Technology GmbH
|
||||||
Liu Liu
|
|
||||||
Liya Li
|
Liya Li
|
||||||
Lu Tang
|
|
||||||
Lu. Pen-ChunX
|
|
||||||
Lubomir Rintel
|
Lubomir Rintel
|
||||||
Luc Verhaegen
|
Luc Verhaegen
|
||||||
Luca Lai
|
|
||||||
Lucas Chen
|
Lucas Chen
|
||||||
Lukas Wunner
|
|
||||||
Mac Chiang
|
Mac Chiang
|
||||||
Maciej Matuszczyk
|
Maciej Matuszczyk
|
||||||
Maciej Pijanowski
|
Maciej Pijanowski
|
||||||
|
|
@ -467,13 +397,11 @@ Marc Bertens
|
||||||
Marc Jones
|
Marc Jones
|
||||||
Marco Chen
|
Marco Chen
|
||||||
Marek Kasiewicz
|
Marek Kasiewicz
|
||||||
Marek Maślanka
|
|
||||||
Marek Vasut
|
Marek Vasut
|
||||||
Mario Scheithauer
|
Mario Scheithauer
|
||||||
Marius Gröger
|
Marius Gröger
|
||||||
Mariusz Szafranski
|
Mariusz Szafranski
|
||||||
Mariusz Szafrański
|
Mariusz Szafrański
|
||||||
Mark Chang
|
|
||||||
Mark Hasemeyer
|
Mark Hasemeyer
|
||||||
Mark Hsieh
|
Mark Hsieh
|
||||||
Mars Chen
|
Mars Chen
|
||||||
|
|
@ -484,7 +412,6 @@ Martin Roth
|
||||||
Marvell International Ltd.
|
Marvell International Ltd.
|
||||||
Marvell Semiconductor Inc.
|
Marvell Semiconductor Inc.
|
||||||
Marx Wang
|
Marx Wang
|
||||||
Masa Nakura
|
|
||||||
Masanori Ogino
|
Masanori Ogino
|
||||||
Máté Kukri
|
Máté Kukri
|
||||||
Matei Dibu
|
Matei Dibu
|
||||||
|
|
@ -493,7 +420,6 @@ Matt Chen
|
||||||
Matt Delco
|
Matt Delco
|
||||||
Matt DeVillier
|
Matt DeVillier
|
||||||
Matt Papageorge
|
Matt Papageorge
|
||||||
Matt Turner
|
|
||||||
Matthew Blecker
|
Matthew Blecker
|
||||||
Matthew Ziegelbaum
|
Matthew Ziegelbaum
|
||||||
Mattias Nissler
|
Mattias Nissler
|
||||||
|
|
@ -506,7 +432,6 @@ Maximilian Brune
|
||||||
Mediatek Inc.
|
Mediatek Inc.
|
||||||
MediaTek Inc.
|
MediaTek Inc.
|
||||||
Meera Ravindranath
|
Meera Ravindranath
|
||||||
Melongmelong
|
|
||||||
Meng-Huan Yu
|
Meng-Huan Yu
|
||||||
Meta Platforms, Inc
|
Meta Platforms, Inc
|
||||||
mgabryelski1
|
mgabryelski1
|
||||||
|
|
@ -519,20 +444,15 @@ Michael Strosche
|
||||||
Michael Walle
|
Michael Walle
|
||||||
Michał Kopeć
|
Michał Kopeć
|
||||||
Michal Suchanek
|
Michal Suchanek
|
||||||
Michał Zieliński
|
|
||||||
Michał Żygowski
|
Michał Żygowski
|
||||||
Micro-Star INT'L CO., LTD.
|
Micro-Star INT'L CO., LTD.
|
||||||
Mika Westerberg
|
Mika Westerberg
|
||||||
Mike Banon
|
Mike Banon
|
||||||
Mike Lin
|
|
||||||
Mike Shih
|
Mike Shih
|
||||||
Mingjin Ge
|
|
||||||
Miriam Polzer
|
Miriam Polzer
|
||||||
mkurumel
|
mkurumel
|
||||||
Moises Garcia
|
Moises Garcia
|
||||||
Momoko Hattori
|
|
||||||
Mondrian Nuessle
|
Mondrian Nuessle
|
||||||
Monika A
|
|
||||||
Monikaanan
|
Monikaanan
|
||||||
MontaVista Software, Inc.
|
MontaVista Software, Inc.
|
||||||
Morgan Jang
|
Morgan Jang
|
||||||
|
|
@ -542,25 +462,21 @@ mtk15698
|
||||||
mturney mturney
|
mturney mturney
|
||||||
Musse Abdullahi
|
Musse Abdullahi
|
||||||
Myles Watson
|
Myles Watson
|
||||||
Nancy Lin
|
Nancy.Lin
|
||||||
Naresh Solanki
|
Naresh Solanki
|
||||||
Nathan Lu
|
Nathan Lu
|
||||||
Naveen R. Iyer
|
|
||||||
Neill Corlett
|
Neill Corlett
|
||||||
Network Appliance Inc.
|
Network Appliance Inc.
|
||||||
Nicholas Chin
|
Nicholas Chin
|
||||||
Nicholas Sielicki
|
Nicholas Sielicki
|
||||||
Nicholas Sudsgaard
|
|
||||||
Nick Barker
|
Nick Barker
|
||||||
Nick Chen
|
Nick Chen
|
||||||
Nick Kochlowski
|
|
||||||
Nick Vaccaro
|
Nick Vaccaro
|
||||||
Nico Huber
|
Nico Huber
|
||||||
Nico Rikken
|
Nico Rikken
|
||||||
Nicola Corna
|
Nicola Corna
|
||||||
Nicolas Boichat
|
Nicolas Boichat
|
||||||
Nicole Faerber
|
Nicole Faerber
|
||||||
Nigel Tao
|
|
||||||
Nikolai Vyssotski
|
Nikolai Vyssotski
|
||||||
Nils Jacobs
|
Nils Jacobs
|
||||||
Nina Wu
|
Nina Wu
|
||||||
|
|
@ -574,10 +490,6 @@ Omar Pakker
|
||||||
Online SAS
|
Online SAS
|
||||||
Opal Voravootivat
|
Opal Voravootivat
|
||||||
Orion Technologies, LLC
|
Orion Technologies, LLC
|
||||||
Ot_chhao.chang
|
|
||||||
Ot_hao.han
|
|
||||||
Ot_song Fan
|
|
||||||
Pablo
|
|
||||||
Pablo Ceballos
|
Pablo Ceballos
|
||||||
Pablo Stebler
|
Pablo Stebler
|
||||||
Pan Gao
|
Pan Gao
|
||||||
|
|
@ -590,7 +502,6 @@ Paul Fagerburg
|
||||||
Paul Menzel
|
Paul Menzel
|
||||||
Paul2 Huang
|
Paul2 Huang
|
||||||
Paulo Alcantara
|
Paulo Alcantara
|
||||||
Pavan Holla
|
|
||||||
Pavel Sayekat
|
Pavel Sayekat
|
||||||
Paz Zcharya
|
Paz Zcharya
|
||||||
PC Engines GmbH
|
PC Engines GmbH
|
||||||
|
|
@ -607,22 +518,17 @@ Philipp Bartsch
|
||||||
Philipp Degler
|
Philipp Degler
|
||||||
Philipp Deppenwiese
|
Philipp Deppenwiese
|
||||||
Philipp Hug
|
Philipp Hug
|
||||||
Pierce Chou
|
|
||||||
Piotr Kleinschmidt
|
Piotr Kleinschmidt
|
||||||
Po Xu
|
Po Xu
|
||||||
Poornima Tom
|
|
||||||
Pranava Y N
|
|
||||||
Prasad Malisetty
|
Prasad Malisetty
|
||||||
Prashant Malani
|
Prashant Malani
|
||||||
Pratik Vishwakarma
|
Pratik Vishwakarma
|
||||||
Pratikkumar Prajapati
|
Pratikkumar Prajapati
|
||||||
Pratikkumar V Prajapati
|
Pratikkumar V Prajapati
|
||||||
Protectli
|
Protectli
|
||||||
PugzAreCute
|
Purism SPC
|
||||||
Purdea Andrei
|
|
||||||
Purism, SPC
|
Purism, SPC
|
||||||
Qii Wang
|
Qii Wang
|
||||||
Qinghong Zeng
|
|
||||||
Qualcomm Technologies, Inc.
|
Qualcomm Technologies, Inc.
|
||||||
Quanta Computer INC
|
Quanta Computer INC
|
||||||
Raihow Shi
|
Raihow Shi
|
||||||
|
|
@ -637,7 +543,6 @@ Ravindra
|
||||||
Ravishankar Sarawadi
|
Ravishankar Sarawadi
|
||||||
Ray Han Lim Ng
|
Ray Han Lim Ng
|
||||||
Raymond Chung
|
Raymond Chung
|
||||||
Reagan
|
|
||||||
Red Hat, Inc
|
Red Hat, Inc
|
||||||
ReddestDream
|
ReddestDream
|
||||||
Rehan Ghori
|
Rehan Ghori
|
||||||
|
|
@ -655,7 +560,6 @@ Richard Woodruff
|
||||||
Rick Lee
|
Rick Lee
|
||||||
Ricky Chang
|
Ricky Chang
|
||||||
Riku Viitanen
|
Riku Viitanen
|
||||||
Rishika Raj
|
|
||||||
Ritul Guru
|
Ritul Guru
|
||||||
Rizwan Qureshi
|
Rizwan Qureshi
|
||||||
Rnhmjoj
|
Rnhmjoj
|
||||||
|
|
@ -668,14 +572,12 @@ Robinson P. Tryon
|
||||||
Rockchip, Inc.
|
Rockchip, Inc.
|
||||||
Rocky Phagura
|
Rocky Phagura
|
||||||
Roger Lu
|
Roger Lu
|
||||||
Roger Wang
|
|
||||||
Roja Rani Yarubandi
|
Roja Rani Yarubandi
|
||||||
Romain Lievin
|
Romain Lievin
|
||||||
Roman Zippel
|
Roman Zippel
|
||||||
Ron Lee
|
Ron Lee
|
||||||
Ron Minnich
|
Ron Minnich
|
||||||
Ronak Kanabar
|
Ronak Kanabar
|
||||||
Ronald Claveau
|
|
||||||
Ronald G. Minnich
|
Ronald G. Minnich
|
||||||
Rory Liu
|
Rory Liu
|
||||||
Rudolf Marek
|
Rudolf Marek
|
||||||
|
|
@ -697,7 +599,6 @@ Samuel Holland
|
||||||
Sandeep Maheswaram
|
Sandeep Maheswaram
|
||||||
Sathya Prakash M R
|
Sathya Prakash M R
|
||||||
Satya Priya Kakitapalli
|
Satya Priya Kakitapalli
|
||||||
Satya SreenivasL
|
|
||||||
Saurabh Mishra
|
Saurabh Mishra
|
||||||
SciTech Software, Inc.
|
SciTech Software, Inc.
|
||||||
Scott Chao
|
Scott Chao
|
||||||
|
|
@ -725,7 +626,6 @@ Shiyu Sun
|
||||||
Shon Wang
|
Shon Wang
|
||||||
Shou-Chieh Hsu
|
Shou-Chieh Hsu
|
||||||
Shreesh Chhabbi
|
Shreesh Chhabbi
|
||||||
Shunxi Zhang
|
|
||||||
Shuo Liu
|
Shuo Liu
|
||||||
Siemens AG
|
Siemens AG
|
||||||
SiFive, Inc
|
SiFive, Inc
|
||||||
|
|
@ -738,12 +638,10 @@ Simon Zhou
|
||||||
Sindhoor Tilak
|
Sindhoor Tilak
|
||||||
Solomon Alan-Dei
|
Solomon Alan-Dei
|
||||||
Song Fan
|
Song Fan
|
||||||
Sowmya Aralguppe
|
|
||||||
Sridhar Siricilla
|
Sridhar Siricilla
|
||||||
Srinidhi N Kaushik
|
Srinidhi N Kaushik
|
||||||
Srinivasa Rao Mandadapu
|
Srinivasa Rao Mandadapu
|
||||||
ST Microelectronics
|
ST Microelectronics
|
||||||
Stanisław Kardach
|
|
||||||
Stanley Wu
|
Stanley Wu
|
||||||
Star Labs Online Ltd
|
Star Labs Online Ltd
|
||||||
Stefan Binding
|
Stefan Binding
|
||||||
|
|
@ -771,7 +669,6 @@ Tao Xia
|
||||||
Tarun Tuli
|
Tarun Tuli
|
||||||
Teddy Shih
|
Teddy Shih
|
||||||
Terry Chen
|
Terry Chen
|
||||||
Terry Cheong
|
|
||||||
Texas Instruments
|
Texas Instruments
|
||||||
The Android Open Source Project
|
The Android Open Source Project
|
||||||
The ChromiumOS Authors
|
The ChromiumOS Authors
|
||||||
|
|
@ -790,9 +687,7 @@ Timothy Pearson
|
||||||
tinghan shen
|
tinghan shen
|
||||||
Tobias Diedrich
|
Tobias Diedrich
|
||||||
Tom Hiller
|
Tom Hiller
|
||||||
Tomasz Michalec
|
|
||||||
Tommie Lin
|
Tommie Lin
|
||||||
Tongtong Pan
|
|
||||||
Tony Huang
|
Tony Huang
|
||||||
Tracy Wu
|
Tracy Wu
|
||||||
Trevor Wu
|
Trevor Wu
|
||||||
|
|
@ -809,13 +704,10 @@ Usha P
|
||||||
Uwe Hermann
|
Uwe Hermann
|
||||||
Uwe Poeche
|
Uwe Poeche
|
||||||
V Sowmya
|
V Sowmya
|
||||||
Vladimir Epifantsev
|
|
||||||
Václav Straka
|
Václav Straka
|
||||||
Vadim Bendebury
|
Vadim Bendebury
|
||||||
Valentyn Sudomyr
|
|
||||||
Van Chen
|
Van Chen
|
||||||
Varshit B Pandya
|
Varshit B Pandya
|
||||||
Varun Upadhyay
|
|
||||||
Veerabhadrarao Badiganti
|
Veerabhadrarao Badiganti
|
||||||
Venkat Thogaru
|
Venkat Thogaru
|
||||||
Venkata Krishna Nimmagadda
|
Venkata Krishna Nimmagadda
|
||||||
|
|
@ -824,7 +716,6 @@ Victor Ding
|
||||||
Vidya Gopalakrishnan
|
Vidya Gopalakrishnan
|
||||||
Vikram Narayanan
|
Vikram Narayanan
|
||||||
Vikrant L Jadeja
|
Vikrant L Jadeja
|
||||||
Vince Liu
|
|
||||||
Vinod Polimera
|
Vinod Polimera
|
||||||
Vipin Kumar
|
Vipin Kumar
|
||||||
Vitaly Rodionov
|
Vitaly Rodionov
|
||||||
|
|
@ -837,10 +728,8 @@ Ward Vandewege
|
||||||
Wayne Wang
|
Wayne Wang
|
||||||
Weimin Wu
|
Weimin Wu
|
||||||
Weiyi Lu
|
Weiyi Lu
|
||||||
Wen Zhang
|
|
||||||
Wenbin Mei
|
Wenbin Mei
|
||||||
Wentao Qin
|
Wentao Qin
|
||||||
Wenzhen Yu
|
|
||||||
Werner Zeh
|
Werner Zeh
|
||||||
Wilbert Duijvenvoorde
|
Wilbert Duijvenvoorde
|
||||||
William Wei
|
William Wei
|
||||||
|
|
@ -857,18 +746,12 @@ Wolfgang Denk
|
||||||
Won Chung
|
Won Chung
|
||||||
Wonkyu Kim
|
Wonkyu Kim
|
||||||
Wuxy
|
Wuxy
|
||||||
Xiang W
|
|
||||||
Xin Ji
|
Xin Ji
|
||||||
Xiwen Shao
|
|
||||||
Xixi Chen
|
Xixi Chen
|
||||||
Xue Yao
|
|
||||||
Xueqi Zhang
|
|
||||||
Xuxin Xiong
|
Xuxin Xiong
|
||||||
YADRO
|
YADRO
|
||||||
Yan Liu
|
Yan Liu
|
||||||
Yang Wu
|
|
||||||
Yann Collet
|
Yann Collet
|
||||||
Yanqiong Huang
|
|
||||||
Yaroslav Kurlaev
|
Yaroslav Kurlaev
|
||||||
YH Lin
|
YH Lin
|
||||||
Yidi Lin
|
Yidi Lin
|
||||||
|
|
@ -883,28 +766,20 @@ Yu-Ping Wu
|
||||||
Yuanliding
|
Yuanliding
|
||||||
Yuchen He
|
Yuchen He
|
||||||
Yuchen Huang
|
Yuchen Huang
|
||||||
Yuchiche
|
|
||||||
Yunlong Jia
|
Yunlong Jia
|
||||||
Yuval Peress
|
|
||||||
Zachary Yedidia
|
Zachary Yedidia
|
||||||
Zanxi Chen
|
Zanxi Chen
|
||||||
Zebreus
|
|
||||||
Zhanyong Wang
|
Zhanyong Wang
|
||||||
Zhaoming Luo
|
|
||||||
Zhaoqing Jiu
|
|
||||||
Zheng Bao
|
Zheng Bao
|
||||||
Zhenguo Li
|
Zhenguo Li
|
||||||
Zhi7 Li
|
Zhi7 Li
|
||||||
Zhigang Qin
|
|
||||||
Zhiqiang Ma
|
Zhiqiang Ma
|
||||||
Zhixing Ma
|
Zhixing Ma
|
||||||
Zhiyong Tao
|
Zhiyong Tao
|
||||||
Zhongtian Wu
|
zhongtian wu
|
||||||
Zhuohao Lee
|
Zhuohao Lee
|
||||||
Ziang Wang
|
Ziang Wang
|
||||||
Zoey Wu
|
Zoey Wu
|
||||||
Zoltan Baldaszti
|
Zoltan Baldaszti
|
||||||
一颗小土豆
|
|
||||||
小田喜陽彦
|
小田喜陽彦
|
||||||
忧郁沙茶
|
|
||||||
陳建宏
|
陳建宏
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
BUILDDIR ?= _build
|
BUILDDIR ?= _build
|
||||||
SPHINXOPTS ?= -j auto -W --keep-going
|
SPHINXOPTS ?= -j auto
|
||||||
|
|
||||||
export SPHINXOPTS
|
export SPHINXOPTS
|
||||||
|
|
||||||
|
|
@ -31,7 +31,8 @@ livesphinx: $(BUILDDIR)
|
||||||
|
|
||||||
test:
|
test:
|
||||||
@echo "Test for logging purposes - Failing tests will not fail the build"
|
@echo "Test for logging purposes - Failing tests will not fail the build"
|
||||||
-$(MAKE) -f Makefile.sphinx clean && $(MAKE) -k -f Makefile.sphinx html
|
-$(MAKE) -f Makefile.sphinx clean && $(MAKE) -K -f Makefile.sphinx html
|
||||||
|
-$(MAKE) -f Makefile.sphinx clean && $(MAKE) -K -f Makefile.sphinx doctest
|
||||||
|
|
||||||
help:
|
help:
|
||||||
@echo "all - Builds all documentation targets"
|
@echo "all - Builds all documentation targets"
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,234 @@
|
||||||
## SPDX-License-Identifier: GPL-2.0-only
|
## SPDX-License-Identifier: GPL-2.0-only
|
||||||
# Minimal makefile for Sphinx documentation
|
# Makefile for Sphinx documentation
|
||||||
#
|
#
|
||||||
|
|
||||||
# You can set these variables from the command line, and also
|
# You can set these variables from the command line.
|
||||||
# from the environment for the first two.
|
SPHINXOPTS ?=
|
||||||
SPHINXOPTS ?=
|
SPHINXBUILD = sphinx-build
|
||||||
SPHINXBUILD ?= sphinx-build
|
SPHINXAUTOBUILD = sphinx-autobuild
|
||||||
SPHINXAUTOBUILD = sphinx-autobuild
|
PAPER =
|
||||||
SOURCEDIR = .
|
BUILDDIR = _build
|
||||||
BUILDDIR = _build
|
|
||||||
|
|
||||||
# Put it first so that "make" without argument is like "make help".
|
# Internal variables.
|
||||||
|
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||||
|
PAPEROPT_letter = -D latex_paper_size=letter
|
||||||
|
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||||
|
# the i18n builder cannot share the environment and doctrees with the others
|
||||||
|
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||||
|
|
||||||
|
.PHONY: help
|
||||||
help:
|
help:
|
||||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
@echo "Please use \`make <target>' where <target> is one of"
|
||||||
|
@echo " html to make standalone HTML files"
|
||||||
|
@echo " dirhtml to make HTML files named index.html in directories"
|
||||||
|
@echo " singlehtml to make a single large HTML file"
|
||||||
|
@echo " pickle to make pickle files"
|
||||||
|
@echo " json to make JSON files"
|
||||||
|
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||||
|
@echo " qthelp to make HTML files and a qthelp project"
|
||||||
|
@echo " applehelp to make an Apple Help Book"
|
||||||
|
@echo " devhelp to make HTML files and a Devhelp project"
|
||||||
|
@echo " epub to make an epub"
|
||||||
|
@echo " epub3 to make an epub3"
|
||||||
|
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||||
|
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||||
|
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
|
||||||
|
@echo " text to make text files"
|
||||||
|
@echo " man to make manual pages"
|
||||||
|
@echo " texinfo to make Texinfo files"
|
||||||
|
@echo " info to make Texinfo files and run them through makeinfo"
|
||||||
|
@echo " gettext to make PO message catalogs"
|
||||||
|
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||||
|
@echo " xml to make Docutils-native XML files"
|
||||||
|
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
|
||||||
|
@echo " linkcheck to check all external links for integrity"
|
||||||
|
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||||
|
@echo " coverage to run coverage check of the documentation (if enabled)"
|
||||||
|
@echo " dummy to check syntax errors of document sources"
|
||||||
|
|
||||||
.PHONY: help Makefile.sphinx
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -rf $(BUILDDIR)
|
||||||
|
|
||||||
|
.PHONY: html
|
||||||
|
html:
|
||||||
|
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||||
|
|
||||||
.PHONY: livehtml
|
.PHONY: livehtml
|
||||||
livehtml:
|
livehtml:
|
||||||
@echo "Starting sphinx-autobuild. The HTML pages are in $(BUILDDIR)."
|
@echo "Starting sphinx-autobuild. The HTML pages are in $(BUILDDIR)."
|
||||||
@echo "Press Ctrl-C to stop."
|
@echo "Press Ctrl-C to stop."
|
||||||
@echo
|
@echo
|
||||||
$(SPHINXAUTOBUILD) "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
$(SPHINXAUTOBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)
|
||||||
|
|
||||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
.PHONY: dirhtml
|
||||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
dirhtml:
|
||||||
%: Makefile.sphinx
|
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
@echo
|
||||||
|
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||||
|
|
||||||
|
.PHONY: singlehtml
|
||||||
|
singlehtml:
|
||||||
|
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||||
|
|
||||||
|
.PHONY: pickle
|
||||||
|
pickle:
|
||||||
|
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can process the pickle files."
|
||||||
|
|
||||||
|
.PHONY: json
|
||||||
|
json:
|
||||||
|
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can process the JSON files."
|
||||||
|
|
||||||
|
.PHONY: htmlhelp
|
||||||
|
htmlhelp:
|
||||||
|
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||||
|
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||||
|
|
||||||
|
.PHONY: qthelp
|
||||||
|
qthelp:
|
||||||
|
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||||
|
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||||
|
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/coreboot.qhcp"
|
||||||
|
@echo "To view the help file:"
|
||||||
|
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/coreboot.qhc"
|
||||||
|
|
||||||
|
.PHONY: applehelp
|
||||||
|
applehelp:
|
||||||
|
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
|
||||||
|
@echo "N.B. You won't be able to view it unless you put it in" \
|
||||||
|
"~/Library/Documentation/Help or install it in your application" \
|
||||||
|
"bundle."
|
||||||
|
|
||||||
|
.PHONY: devhelp
|
||||||
|
devhelp:
|
||||||
|
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished."
|
||||||
|
@echo "To view the help file:"
|
||||||
|
@echo "# mkdir -p $$HOME/.local/share/devhelp/coreboot"
|
||||||
|
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/coreboot"
|
||||||
|
@echo "# devhelp"
|
||||||
|
|
||||||
|
.PHONY: epub
|
||||||
|
epub:
|
||||||
|
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||||
|
|
||||||
|
.PHONY: epub3
|
||||||
|
epub3:
|
||||||
|
$(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
|
||||||
|
|
||||||
|
.PHONY: latex
|
||||||
|
latex:
|
||||||
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||||
|
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||||
|
"(use \`make latexpdf' here to do that automatically)."
|
||||||
|
|
||||||
|
.PHONY: latexpdf
|
||||||
|
latexpdf:
|
||||||
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
|
@echo "Running LaTeX files through pdflatex..."
|
||||||
|
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||||
|
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||||
|
|
||||||
|
.PHONY: latexpdfja
|
||||||
|
latexpdfja:
|
||||||
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
|
@echo "Running LaTeX files through platex and dvipdfmx..."
|
||||||
|
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
|
||||||
|
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||||
|
|
||||||
|
.PHONY: text
|
||||||
|
text:
|
||||||
|
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||||
|
|
||||||
|
.PHONY: man
|
||||||
|
man:
|
||||||
|
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||||
|
|
||||||
|
.PHONY: texinfo
|
||||||
|
texinfo:
|
||||||
|
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||||
|
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||||
|
"(use \`make info' here to do that automatically)."
|
||||||
|
|
||||||
|
.PHONY: info
|
||||||
|
info:
|
||||||
|
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||||
|
@echo "Running Texinfo files through makeinfo..."
|
||||||
|
make -C $(BUILDDIR)/texinfo info
|
||||||
|
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||||
|
|
||||||
|
.PHONY: gettext
|
||||||
|
gettext:
|
||||||
|
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||||
|
|
||||||
|
.PHONY: changes
|
||||||
|
changes:
|
||||||
|
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||||
|
@echo
|
||||||
|
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||||
|
|
||||||
|
.PHONY: linkcheck
|
||||||
|
linkcheck:
|
||||||
|
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||||
|
@echo
|
||||||
|
@echo "Link check complete; look for any errors in the above output " \
|
||||||
|
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||||
|
|
||||||
|
.PHONY: doctest
|
||||||
|
doctest:
|
||||||
|
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||||
|
@echo "Testing of doctests in the sources finished, look at the " \
|
||||||
|
"results in $(BUILDDIR)/doctest/output.txt."
|
||||||
|
|
||||||
|
.PHONY: coverage
|
||||||
|
coverage:
|
||||||
|
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
|
||||||
|
@echo "Testing of coverage in the sources finished, look at the " \
|
||||||
|
"results in $(BUILDDIR)/coverage/python.txt."
|
||||||
|
|
||||||
|
.PHONY: xml
|
||||||
|
xml:
|
||||||
|
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
|
||||||
|
|
||||||
|
.PHONY: pseudoxml
|
||||||
|
pseudoxml:
|
||||||
|
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
||||||
|
|
||||||
|
.PHONY: dummy
|
||||||
|
dummy:
|
||||||
|
$(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. Dummy builder generates no files."
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ coreboot POST Codes
|
||||||
This is an (incomplete) list of POST codes emitted by coreboot v4.
|
This is an (incomplete) list of POST codes emitted by coreboot v4.
|
||||||
|
|
||||||
0x10 Entry into protected mode
|
0x10 Entry into protected mode
|
||||||
0x01 Entry into 'entry16.S' reset code jumps to here
|
0x01 Entry into 'crt0.s' reset code jumps to here
|
||||||
0x11 Start copying coreboot to RAM with decompression if compressed
|
0x11 Start copying coreboot to RAM with decompression if compressed
|
||||||
0x12 Copy/decompression finished jumping to RAM
|
0x12 Copy/decompression finished jumping to RAM
|
||||||
0x80 Entry into coreboot in RAM
|
0x80 Entry into coreboot in RAM
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,3 @@
|
||||||
```{eval-rst}
|
|
||||||
:orphan:
|
|
||||||
```
|
|
||||||
|
|
||||||
# Background
|
# Background
|
||||||
|
|
||||||
CB:31250 ("soc/intel/cannonlake: Configure GPIOs again after FSP-S is
|
CB:31250 ("soc/intel/cannonlake: Configure GPIOs again after FSP-S is
|
||||||
|
|
|
||||||
|
|
@ -5,27 +5,15 @@ backwards support for ACPI 1.0 and is only compatible to ACPI version 2.0 and
|
||||||
upwards.
|
upwards.
|
||||||
|
|
||||||
|
|
||||||
```{toctree}
|
- [SSDT UID generation](uid.md)
|
||||||
:maxdepth: 1
|
|
||||||
|
|
||||||
SSDT UID generation <uid.md>
|
|
||||||
```
|
|
||||||
|
|
||||||
## GPIO
|
## GPIO
|
||||||
|
|
||||||
```{toctree}
|
- [GPIO toggling in ACPI AML](gpio.md)
|
||||||
:maxdepth: 1
|
|
||||||
|
|
||||||
GPIO toggling in ACPI AML <gpio.md>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Windows-specific ACPI documentation
|
## Windows-specific ACPI documentation
|
||||||
|
|
||||||
```{toctree}
|
- [Windows-specific documentation](windows.md)
|
||||||
:maxdepth: 1
|
|
||||||
|
|
||||||
Windows-specific documentation <windows.md>
|
|
||||||
```
|
|
||||||
|
|
||||||
## ACPI specification - Useful links
|
## ACPI specification - Useful links
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ Spec](https://uefi.org/specifications) for details, or run the tool
|
||||||
initialization that happens from the PSP. Significantly, Memory
|
initialization that happens from the PSP. Significantly, Memory
|
||||||
Initialization.
|
Initialization.
|
||||||
* AC - Electricity: [**Alternating Current**](https://en.wikipedia.org/wiki/Alternating_current)
|
* AC - Electricity: [**Alternating Current**](https://en.wikipedia.org/wiki/Alternating_current)
|
||||||
* ACE - AXI Coherency Extensions
|
|
||||||
* Ack - Acknowledgment / Acknowledged
|
* Ack - Acknowledgment / Acknowledged
|
||||||
* ACM – [**Authenticated Code Module**](https://doc.coreboot.org/security/intel/acm.html)
|
* ACM – [**Authenticated Code Module**](https://doc.coreboot.org/security/intel/acm.html)
|
||||||
* ACP - [**Average CPU power**](https://en.wikipedia.org/wiki/Thermal_design_power)
|
* ACP - [**Average CPU power**](https://en.wikipedia.org/wiki/Thermal_design_power)
|
||||||
|
|
@ -57,14 +56,11 @@ Spec](https://uefi.org/specifications) for details, or run the tool
|
||||||
* AMT - Intel: [**Active Management Technology**](https://en.wikipedia.org/wiki/Intel_Active_Management_Technology)
|
* AMT - Intel: [**Active Management Technology**](https://en.wikipedia.org/wiki/Intel_Active_Management_Technology)
|
||||||
* ANSI - [**American National Standards Institute**](https://en.wikipedia.org/wiki/American_National_Standards_Institute)
|
* ANSI - [**American National Standards Institute**](https://en.wikipedia.org/wiki/American_National_Standards_Institute)
|
||||||
* AOAC - AMD: Always On, Always Connected
|
* AOAC - AMD: Always On, Always Connected
|
||||||
* AON - Always ON: Sometimes used for power domains that are always on (e.g. RTC, GPIOs, Wake on LAN ...)
|
|
||||||
* AP - Application processor - The main processor on the board (as
|
* AP - Application processor - The main processor on the board (as
|
||||||
opposed to the embedded controller or other processors that may be on
|
opposed to the embedded controller or other processors that may be on
|
||||||
the system), any cores in the processor chip that aren't the BSP (Boot
|
the system), any cores in the processor chip that aren't the BSP (Boot
|
||||||
Strap Processor).
|
Strap Processor).
|
||||||
* APB - Advanced Peripheral Bus (part of the AMBA bus specification)
|
|
||||||
* APCB - AMD: AMD PSP Customization Block
|
* APCB - AMD: AMD PSP Customization Block
|
||||||
* AHB - Advanced High-performance Bus (part of the AMBA bus specification)
|
|
||||||
* API - [**Application Programming Interface**](https://en.wikipedia.org/wiki/API)
|
* API - [**Application Programming Interface**](https://en.wikipedia.org/wiki/API)
|
||||||
* APIC - [**Advanced Programmable Interrupt
|
* APIC - [**Advanced Programmable Interrupt
|
||||||
Controller**](https://en.wikipedia.org/wiki/Advanced_Programmable_Interrupt_Controller)
|
Controller**](https://en.wikipedia.org/wiki/Advanced_Programmable_Interrupt_Controller)
|
||||||
|
|
@ -98,7 +94,7 @@ Spec](https://uefi.org/specifications) for details, or run the tool
|
||||||
* ATAPI - [**ATA Packet Interface**](https://en.wikipedia.org/wiki/Parallel_ATA#ATAPI)
|
* ATAPI - [**ATA Packet Interface**](https://en.wikipedia.org/wiki/Parallel_ATA#ATAPI)
|
||||||
* ATX - [**Advanced Technology eXtended**](https://en.wikipedia.org/wiki/ATX)
|
* ATX - [**Advanced Technology eXtended**](https://en.wikipedia.org/wiki/ATX)
|
||||||
* AVX - [**Advanced Vector Extensions**](https://en.wikipedia.org/wiki/Advanced_Vector_Extensions)
|
* AVX - [**Advanced Vector Extensions**](https://en.wikipedia.org/wiki/Advanced_Vector_Extensions)
|
||||||
* AXI - [Advanced eXtensible Interface](https://en.wikipedia.org/wiki/Advanced_eXtensible_Interface) part of the AMBA bus specification
|
|
||||||
|
|
||||||
## B
|
## B
|
||||||
|
|
||||||
|
|
@ -173,7 +169,6 @@ Spec](https://uefi.org/specifications) for details, or run the tool
|
||||||
* CDN - [**Content Delivery Network**](https://en.wikipedia.org/wiki/Content_delivery_network)
|
* CDN - [**Content Delivery Network**](https://en.wikipedia.org/wiki/Content_delivery_network)
|
||||||
* CEM - PCIe: [**Card ElectroMechanical**](https://members.pcisig.com/wg/PCI-SIG/document/folder/839) specification
|
* CEM - PCIe: [**Card ElectroMechanical**](https://members.pcisig.com/wg/PCI-SIG/document/folder/839) specification
|
||||||
* CFL - [**Coffee Lake**](https://en.wikichip.org/wiki/intel/microarchitectures/coffee_lake)
|
* CFL - [**Coffee Lake**](https://en.wikichip.org/wiki/intel/microarchitectures/coffee_lake)
|
||||||
* CHI - Coherent Hub Interface
|
|
||||||
* CID - [**Coverity ID**](https://en.wikipedia.org/wiki/Coverity)
|
* CID - [**Coverity ID**](https://en.wikipedia.org/wiki/Coverity)
|
||||||
* CIM - [**Common Information Model**](https://www.dmtf.org/standards/cim)
|
* CIM - [**Common Information Model**](https://www.dmtf.org/standards/cim)
|
||||||
* CISC - [**Complex Instruction Set Computer**](https://en.wikipedia.org/wiki/Complex_instruction_set_computer)
|
* CISC - [**Complex Instruction Set Computer**](https://en.wikipedia.org/wiki/Complex_instruction_set_computer)
|
||||||
|
|
@ -204,6 +199,7 @@ Spec](https://uefi.org/specifications) for details, or run the tool
|
||||||
* CRLF - Carriage Return, Line Feed - \\r\\n - The standard window EOL
|
* CRLF - Carriage Return, Line Feed - \\r\\n - The standard window EOL
|
||||||
(End-of-Line) marker.
|
(End-of-Line) marker.
|
||||||
* crt0 - [**C Run Time 0**](https://en.wikipedia.org/wiki/Crt0)
|
* crt0 - [**C Run Time 0**](https://en.wikipedia.org/wiki/Crt0)
|
||||||
|
* crt0s - crt0 Source code
|
||||||
* CRT - [**Cathode Ray Tube**](https://en.wikipedia.org/wiki/Cathode-ray_tube)
|
* CRT - [**Cathode Ray Tube**](https://en.wikipedia.org/wiki/Cathode-ray_tube)
|
||||||
* CSE - Intel: Converged Security Engine
|
* CSE - Intel: Converged Security Engine
|
||||||
* CSI - MIPI: [**Camera Serial
|
* CSI - MIPI: [**Camera Serial
|
||||||
|
|
@ -408,7 +404,7 @@ Spec](https://uefi.org/specifications) for details, or run the tool
|
||||||
* GPD - PCH GPIO in Deep Sleep well (D5 power)
|
* GPD - PCH GPIO in Deep Sleep well (D5 power)
|
||||||
* GPE - ACPI: General Purpose Event
|
* GPE - ACPI: General Purpose Event
|
||||||
* GPI - GPIOs: GPIO Input
|
* GPI - GPIOs: GPIO Input
|
||||||
* GPIO - [**General Purpose Input/Output**](https://en.wikipedia.org/wiki/General-purpose_input/output) (Pin)
|
* GPIO - [**General Purpose Input/Output**](https://en.wikipedia.org/wiki/General-purpose_Input/Output) (Pin)
|
||||||
* GPMR - Intel: General Purpose Memory Range
|
* GPMR - Intel: General Purpose Memory Range
|
||||||
* GPO - GPIOs: GPIO Output
|
* GPO - GPIOs: GPIO Output
|
||||||
* GPP - AMD: General Purpose (PCI/PCIe) port
|
* GPP - AMD: General Purpose (PCI/PCIe) port
|
||||||
|
|
@ -521,7 +517,6 @@ Spec](https://uefi.org/specifications) for details, or run the tool
|
||||||
processor to help offload data processing from various sensors on a
|
processor to help offload data processing from various sensors on a
|
||||||
mainboard.
|
mainboard.
|
||||||
* ISP - Internet Service Provider
|
* ISP - Internet Service Provider
|
||||||
* ISP - Image-Signal-Process
|
|
||||||
* IVHD - ACPI: I/O Virtualization Hardware Definition
|
* IVHD - ACPI: I/O Virtualization Hardware Definition
|
||||||
* IVMD - ACPI: I/O Virtualization Memory Definition
|
* IVMD - ACPI: I/O Virtualization Memory Definition
|
||||||
* IVRS - I/O Virtualization Reporting Structure
|
* IVRS - I/O Virtualization Reporting Structure
|
||||||
|
|
@ -995,7 +990,6 @@ Spec](https://uefi.org/specifications) for details, or run the tool
|
||||||
* SSPHY - USB: USB3 Super-Speed PHY
|
* SSPHY - USB: USB3 Super-Speed PHY
|
||||||
* STAPM - AMD: Skin Temperature Aware Power Management
|
* STAPM - AMD: Skin Temperature Aware Power Management
|
||||||
* STB - AMD: Smart Trace Buffer
|
* STB - AMD: Smart Trace Buffer
|
||||||
* STG - System-Top-Group apparently a term for grouping subsystems in an SOC together?
|
|
||||||
* SuperIO - The [**Super I/O**](https://en.wikipedia.org/wiki/Super_I/O)
|
* SuperIO - The [**Super I/O**](https://en.wikipedia.org/wiki/Super_I/O)
|
||||||
(SIO) device provides a system with any of a number of different
|
(SIO) device provides a system with any of a number of different
|
||||||
peripherals. Most common are: A PS/2 Keyboard and mouse port, LPT
|
peripherals. Most common are: A PS/2 Keyboard and mouse port, LPT
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,7 @@ architectures.
|
||||||
|
|
||||||
## RISC-V
|
## RISC-V
|
||||||
|
|
||||||
```{toctree}
|
- [RISC-V documentation](riscv/index.md)
|
||||||
:maxdepth: 1
|
|
||||||
|
|
||||||
RISC-V documentation <riscv/index.md>
|
|
||||||
```
|
|
||||||
|
|
||||||
## x86
|
## x86
|
||||||
```{toctree}
|
- [x86 documentation](x86/index.md)
|
||||||
:maxdepth: 1
|
|
||||||
|
|
||||||
x86 documentation <x86/index.md>
|
|
||||||
```
|
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,94 @@
|
||||||
|
|
||||||
This section contains documentation about coreboot on x86 architecture.
|
This section contains documentation about coreboot on x86 architecture.
|
||||||
|
|
||||||
```{toctree}
|
* [x86 PAE support](pae.md)
|
||||||
:maxdepth: 1
|
|
||||||
|
|
||||||
x86 PAE support <pae.md>
|
## State of x86_64 support
|
||||||
x86_64 support <x86_64.md>
|
At the moment there's only experimental x86_64 support.
|
||||||
```
|
The `emulation/qemu-i440fx` and `emulation/qemu-q35` boards do support
|
||||||
|
*ARCH_RAMSTAGE_X86_64* , *ARCH_POSTCAR_X86_64* and *ARCH_ROMSTAGE_X86_64*.
|
||||||
|
|
||||||
|
In order to add support for x86_64 the following assumptions were made:
|
||||||
|
* The CPU supports long mode
|
||||||
|
* All memory returned by malloc must be below 4GiB in physical memory
|
||||||
|
* All code that is to be run must be below 4GiB in physical memory
|
||||||
|
* The high dword of pointers is always zero
|
||||||
|
* The reference implementation is qemu
|
||||||
|
* The CPU supports 1GiB hugepages
|
||||||
|
* x86 payloads are loaded below 4GiB in physical memory and are jumped
|
||||||
|
to in *protected mode*
|
||||||
|
|
||||||
|
## Assumptions for all stages using the reference implementation
|
||||||
|
* 0-4GiB are identity mapped using 2MiB-pages as WB
|
||||||
|
* Memory above 4GiB isn't accessible
|
||||||
|
* page tables reside in memory mapped ROM
|
||||||
|
* A stage can install new page tables in RAM
|
||||||
|
|
||||||
|
## Page tables
|
||||||
|
A `pagetables` cbfs file is generated based on an assembly file.
|
||||||
|
|
||||||
|
To generate the static page tables it must know the physical address where to
|
||||||
|
place the file.
|
||||||
|
|
||||||
|
The page tables contains the following structure:
|
||||||
|
* PML4E pointing to PDPE
|
||||||
|
* PDPE with *$n* entries each pointing to PDE
|
||||||
|
* *$n* PDEs with 512 entries each
|
||||||
|
|
||||||
|
At the moment *$n* is 4, which results in identity mapping the lower 4 GiB.
|
||||||
|
|
||||||
|
## Basic x86_64 support
|
||||||
|
Basic support for x86_64 has been implemented for QEMU mainboard target.
|
||||||
|
|
||||||
|
## Reference implementation
|
||||||
|
The reference implementation is
|
||||||
|
* [QEMU i440fx](../../mainboard/emulation/qemu-i440fx.md)
|
||||||
|
* [QEMU Q35](../../mainboard/emulation/qemu-q35.md)
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
* Identity map memory above 4GiB in ramstage
|
||||||
|
|
||||||
|
## Future work
|
||||||
|
|
||||||
|
1. Fine grained page tables for SMM:
|
||||||
|
* Must not have execute and write permissions for the same page.
|
||||||
|
* Must allow only that TSEG pages can be marked executable
|
||||||
|
* Must reside in SMRAM
|
||||||
|
2. Support 64bit PCI BARs above 4GiB
|
||||||
|
3. Place and run code above 4GiB
|
||||||
|
|
||||||
|
## Porting other boards
|
||||||
|
* Fix compilation errors
|
||||||
|
* Test how well CAR works with x86_64 and paging
|
||||||
|
* Improve mode switches
|
||||||
|
* Test libgfxinit / VGA Option ROMs / FSP
|
||||||
|
|
||||||
|
## Known bugs on real hardware
|
||||||
|
|
||||||
|
According to Intel x86_64 mode hasn't been validated in CAR environments.
|
||||||
|
Until now it could be verified on various Intel platforms and no issues have
|
||||||
|
been found.
|
||||||
|
|
||||||
|
## Known bugs on KVM enabled qemu
|
||||||
|
|
||||||
|
The `x86_64` reference code runs fine in qemu soft-cpu, but has serious issues
|
||||||
|
when using KVM mode on some machines. The workaround is to *not* place
|
||||||
|
page-tables in ROM, as done in
|
||||||
|
[CB:49228](https://review.coreboot.org/c/coreboot/+/49228).
|
||||||
|
|
||||||
|
Here's a list of known issues:
|
||||||
|
|
||||||
|
* After entering long mode, the FPU doesn't work anymore, including accessing
|
||||||
|
MMX registers. It works fine before entering long mode. It works fine when
|
||||||
|
switching back to protected mode. Other registers, like SSE registers, are
|
||||||
|
working fine.
|
||||||
|
* Reading from virtual memory, when the page tables are stored in ROM, causes
|
||||||
|
the MMU to abort the "page table walking" mechanism when the lower address
|
||||||
|
bits of the virtual address to be translated have a specific pattern.
|
||||||
|
Instead of loading the correct physical page, the one containing the
|
||||||
|
page tables in ROM will be loaded and used, which breaks code and data as
|
||||||
|
the page table doesn't contain the expected data. This in turn leads to
|
||||||
|
undefined behaviour whenever the 'wrong' address is being read.
|
||||||
|
* Disabling paging in compatibility mode crashes the CPU.
|
||||||
|
* Returning from long mode to compatibility mode crashes the CPU.
|
||||||
|
* Entering long mode crashes on AMD host platforms.
|
||||||
|
|
|
||||||
|
|
@ -1,109 +0,0 @@
|
||||||
# x86_64 architecture documentation
|
|
||||||
|
|
||||||
This section documents coreboot's x86_64 support. When enabled,
|
|
||||||
every coreboot stage is built for x86_64, contrary to UEFI's implementation
|
|
||||||
that only runs some stages in x86_64.
|
|
||||||
On UEFI the PEI phase, which is x86_32, brings up DRAM and installs
|
|
||||||
page tables for the x86_64 DXE and BDS phases.
|
|
||||||
|
|
||||||
## Toolchain requirements for x86_64 support
|
|
||||||
* The compiler must support generating code for the *large memory model*
|
|
||||||
(-mcmodel=large). It's supported since GCC 4.4.
|
|
||||||
|
|
||||||
Page tables can be used to provide security benefits, such as by marking
|
|
||||||
memory as non-executable or removing it entirely. This could be useful
|
|
||||||
for SMM to mark regular DRAM as NX.
|
|
||||||
|
|
||||||
The large memory model causes the compiler to emit 64bit addressing
|
|
||||||
instructions, which increases code size. In theory, this is roughly
|
|
||||||
made up for by the faster execution of the x86_64 code.
|
|
||||||
|
|
||||||
* All x86 coreboot stages and payloads must be loaded below 4GiB in
|
|
||||||
physical memory. When jumping to the payload coreboot will drop from
|
|
||||||
long mode back to protected mode to keep compatibility with these payloads.
|
|
||||||
|
|
||||||
## Comparison to UEFI
|
|
||||||
On UEFI the SEC and PEI phases (similar to coreboot's bootblock and romstage)
|
|
||||||
are run in x86_32 mode. The following (guessed) reasons are likely:
|
|
||||||
* There's no need for x86_64 as memory hasn't been trained yet. The whole 4GiB
|
|
||||||
address space, including CAR, memory mapped SPI flash and PCI BARs, are
|
|
||||||
accessible in x86_32.
|
|
||||||
* When the EFI specification was written compilers did not support
|
|
||||||
*large memory model*, required in CAR when using a 1:1 page mapping
|
|
||||||
* Code is 20% bigger in x86_64 due to *large memory model* where pointers and
|
|
||||||
function calls always use 8 byte addressing. However flash size was very
|
|
||||||
limited, compared to today's flash chips, when the EFI spec was written.
|
|
||||||
|
|
||||||
## Current software constraints for x86_64 support
|
|
||||||
The following constraints are coreboot limitations as it was intended to run in
|
|
||||||
protected mode only. The code still assumes 32bit pointers in some places and thus:
|
|
||||||
* The high dword of pointers must always be zero.
|
|
||||||
* All memory returned by malloc must be below 4GiB in physical memory.
|
|
||||||
* All code that is to be run must be below 4GiB in physical memory.
|
|
||||||
* CBMEM must reside below 4GiB in physical memory.
|
|
||||||
|
|
||||||
Any software within coreboot must not access memory resources above 4GiB until
|
|
||||||
end of BS_DEV_RESOURCES in ramstage. Only at that point the full memory map is
|
|
||||||
known and identity mapped.
|
|
||||||
|
|
||||||
## Supported boards
|
|
||||||
On the supported boards you can enable x86_64 compilation by setting the
|
|
||||||
Kconfig `USE_X86_64_SUPPORT`. This config option is enabled if the SOC/CPU
|
|
||||||
selects `HAVE_X86_64_SUPPORT`.
|
|
||||||
|
|
||||||
## Protected mode wrappers
|
|
||||||
On some platforms binary blobs are run to initialize parts of the hardware.
|
|
||||||
When these binary blobs have been compiled for x86_32, then coreboot must
|
|
||||||
switch to protected mode in order to call and run the blobs. Once the invoked
|
|
||||||
blobs finish running, coreboot needs to switch back to long mode.
|
|
||||||
|
|
||||||
Since every BLOB is different a SoC must be enabled to support x86_64 mode
|
|
||||||
by providing the correct wrapper around the x86_32 BLOBs.
|
|
||||||
|
|
||||||
## TODO
|
|
||||||
* Support more platforms
|
|
||||||
* Fix running VGA Option ROMs
|
|
||||||
* Fix running MRC.bin (Sandy Bridge / Haswell boards)
|
|
||||||
* Identity map memory above 4GiB in ramstage
|
|
||||||
* Fine grained page tables for SMM:
|
|
||||||
* Must not have execute and write permissions for the same page.
|
|
||||||
* Must only allow TSEG pages to be marked as executable.
|
|
||||||
* Must reside in SMRAM.
|
|
||||||
* Must be placed together with SMM rmodule.
|
|
||||||
* Support 64bit PCI BARs above 4GiB
|
|
||||||
* Jump to compatible payloads in long mode
|
|
||||||
|
|
||||||
## Porting other boards
|
|
||||||
* Fix compilation errors
|
|
||||||
* Test how well CAR works with x86_64 and paging
|
|
||||||
* Improve mode switches
|
|
||||||
* Test libgfxinit / VGA Option ROMs / FSP
|
|
||||||
|
|
||||||
## Known bugs on real hardware
|
|
||||||
|
|
||||||
According to Intel x86_64 mode hasn't been validated in CAR environments.
|
|
||||||
However, coreboot developers working on x86_64 support have tried this on
|
|
||||||
various Intel platforms, and so far haven't found any issues with CAR when
|
|
||||||
running in x86_64 mode.
|
|
||||||
|
|
||||||
## Known bugs on KVM enabled QEMU
|
|
||||||
|
|
||||||
The `x86_64` reference code runs fine in QEMU's soft-cpu, but has serious issues
|
|
||||||
when using KVM mode on some machines. This is due to various mechanisms trying
|
|
||||||
to accelerate the code execution.
|
|
||||||
|
|
||||||
Known issues in QEMU:
|
|
||||||
* After entering long mode, the FPU doesn't work anymore, including accessing
|
|
||||||
MMX registers. It works fine before entering long mode. It works fine when
|
|
||||||
switching back to protected mode. Other registers, like SSE registers, are
|
|
||||||
working fine.
|
|
||||||
* Reading from virtual memory, when the page tables are stored in ROM, causes
|
|
||||||
the MMU to abort the "page table walking" mechanism when the lower address
|
|
||||||
bits of the virtual address to be translated have a specific pattern.
|
|
||||||
Instead of loading the correct physical page, the one containing the
|
|
||||||
page tables in ROM will be loaded and used, which breaks code and data as
|
|
||||||
the page table doesn't contain the expected data. This in turn leads to
|
|
||||||
undefined behaviour whenever the 'wrong' address is being read.
|
|
||||||
* Disabling paging in compatibility mode crashes the CPU.
|
|
||||||
* Returning from long mode to compatibility mode crashes the CPU.
|
|
||||||
* Entering long mode crashes on AMD host platforms.
|
|
||||||
|
|
@ -86,13 +86,8 @@ organizers may take any action they deem appropriate, up to and including
|
||||||
a temporary ban or permanent expulsion from the community without warning
|
a temporary ban or permanent expulsion from the community without warning
|
||||||
(and without refund in the case of a paid event).
|
(and without refund in the case of a paid event).
|
||||||
|
|
||||||
As a part of running the project, coreboot leadership has the right to
|
Community organizers can be members of the arbitration team, or organizers
|
||||||
revoke privileges as they see fit. This is not done lightly. Over the
|
of events and online communities.
|
||||||
history of the coreboot project, there have been only a handful of times
|
|
||||||
where an action needed to be taken.
|
|
||||||
|
|
||||||
Community organizers can be members of the arbitration team, the
|
|
||||||
leadership board, or organizers of events and online communities.
|
|
||||||
|
|
||||||
## Addressing Grievances
|
## Addressing Grievances
|
||||||
|
|
||||||
|
|
@ -100,11 +95,6 @@ If you feel you have been falsely or unfairly accused of violating this
|
||||||
Code of Conduct, you should notify the arbitration team with a concise
|
Code of Conduct, you should notify the arbitration team with a concise
|
||||||
description of your grievance.
|
description of your grievance.
|
||||||
|
|
||||||
Discussions about these actions are not done publicly, for obvious
|
|
||||||
reasons. If someone believes that the circumstances that led to an
|
|
||||||
action have changed, please send an email to all the members of the
|
|
||||||
arbitration team and/or leadership board for discussion.
|
|
||||||
|
|
||||||
## Legal action
|
## Legal action
|
||||||
|
|
||||||
Threatening or starting legal action against the project, sibling
|
Threatening or starting legal action against the project, sibling
|
||||||
|
|
@ -125,18 +115,12 @@ communications pertaining to community business.
|
||||||
|
|
||||||
## Contact info
|
## Contact info
|
||||||
|
|
||||||
Our arbitration team currently consists of the following people
|
Our arbitration team consists of the following people
|
||||||
* Daniel Pono Takamori <pono@sfconservancy.org> (USA)
|
* Stefan Reinauer <stefan.reinauer@coreboot.org> (USA)
|
||||||
|
* Patrick Georgi <patrick@coreboot.org> (Germany)
|
||||||
* Ronald Minnich <rminnich@coreboot.org> (USA)
|
* Ronald Minnich <rminnich@coreboot.org> (USA)
|
||||||
* Martin Roth <martin@coreboot.org> (USA)
|
* Martin Roth <martin@coreboot.org> (USA)
|
||||||
|
|
||||||
If you have an issue with someone on the arbitration team, please reach
|
|
||||||
out to the coreboot leadership board directly.
|
|
||||||
|
|
||||||
The leadership board's information can be found on the
|
|
||||||
[coreboot Leadership and Admin Boards](https://coreboot.org/leadership.html)
|
|
||||||
page on the website.
|
|
||||||
|
|
||||||
## License and attribution
|
## License and attribution
|
||||||
|
|
||||||
This Code of Conduct is distributed under
|
This Code of Conduct is distributed under
|
||||||
|
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
# Cross-Project Collaboration
|
|
||||||
|
|
||||||
Open source firmware has become popular and important over the last several
|
|
||||||
decades and is currently anchored in multiple key applications like industry,
|
|
||||||
automotive, infrastructure and commodity PC systems. coreboot has a
|
|
||||||
long-reaching history in all these applications and has become a vital
|
|
||||||
alternative to proprietary firmware solutions. Since coreboot itself is
|
|
||||||
minimalistic, other open source projects like SeaBIOS and flashrom help complete
|
|
||||||
the overall user experience by providing a well established way to boot into an
|
|
||||||
OS and easily reprogram the firmware on demand.
|
|
||||||
|
|
||||||
Open source projects often lack funds and are heavily dependent on volunteer
|
|
||||||
work by enthusiasts. coreboot has made its way over the many years it’s been
|
|
||||||
running and is now able to operate its own paid infrastructure for various
|
|
||||||
services like git, Gerrit and Jenkins, all of them are key factors for a
|
|
||||||
worldwide collaboration and project success. Other small but still important
|
|
||||||
projects do not have such resources and face infrastructure issues more often.
|
|
||||||
|
|
||||||
Furthermore, often the same people do work for different open source projects.
|
|
||||||
Therefore, it is important to support such projects where feasible.
|
|
||||||
For instance, sharing the IT infrastructure can leverage quite some synergies
|
|
||||||
as the tasks for different projects are quite similar, e.g. push code to public,
|
|
||||||
review it in Gerrit, let Jenkins do a build and report back to Gerrit or provide
|
|
||||||
a bug tracker platform where users and developers can report bugs and issues.
|
|
||||||
The coreboot project already has servers providing such services and these have
|
|
||||||
a huge amount of headroom to execute such tasks for other projects.
|
|
||||||
Additionally, the developers working on multiple projects are supported as they
|
|
||||||
can do their work with the same mindset while interfacing with common services
|
|
||||||
among different projects. This not only improves cross-project collaboration but
|
|
||||||
also does improve code quality because the developers do not have to switch
|
|
||||||
between different project setups.
|
|
||||||
|
|
||||||
Therefore, the coreboot project explicitly encourages collaboration with other
|
|
||||||
open source projects in the firmware domain. Especially the already well
|
|
||||||
established partnership with flashrom, SeaBIOS, and EM100 should continue to be
|
|
||||||
maintained further on. This includes:
|
|
||||||
|
|
||||||
* Sharing of the IT infrastructure
|
|
||||||
* Sharing the critical services like git, Gerrit, Jenkins and the bugtracker
|
|
||||||
* Sharing of the established communication methods via mailing list, Slack, IRC
|
|
||||||
or Discord
|
|
||||||
* Sharing web services for web page or wikis and blog posts
|
|
||||||
|
|
||||||
If there is interest in a collaboration, please reach out to
|
|
||||||
coreboot@coreboot.org.
|
|
||||||
|
|
||||||
The coreboot project is still responsible and in charge of its offered services
|
|
||||||
to partner projects. The technical details of the collaboration will be
|
|
||||||
discussed on a case-by-case basis with affected parties where coreboot project
|
|
||||||
infrastructure maintainers have the lead.
|
|
||||||
|
|
||||||
Note that it is expected that everyone using the coreboot services is expected
|
|
||||||
to follow coreboot code-of-conduct policies at all times. In cases where the
|
|
||||||
coreboot CoC is broken by someone working only on other projects in the coreboot
|
|
||||||
infrastructure, the coreboot leadership will work with the leadership of the
|
|
||||||
other project on the issue.
|
|
||||||
|
|
@ -1,11 +1,6 @@
|
||||||
# Community
|
# Community
|
||||||
|
|
||||||
```{toctree}
|
* [Code of Conduct](code_of_conduct.md)
|
||||||
:maxdepth: 1
|
* [Language style](language_style.md)
|
||||||
|
* [Community forums](forums.md)
|
||||||
Code of Conduct <code_of_conduct.md>
|
* [coreboot at conferences](conferences.md)
|
||||||
Language style <language_style.md>
|
|
||||||
Community forums <forums.md>
|
|
||||||
coreboot at conferences <conferences.md>
|
|
||||||
Cross-Project Collaboration <cross_project_collaboration.md>
|
|
||||||
```
|
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,54 @@
|
||||||
# Configuration file for the Sphinx documentation builder.
|
# -*- coding: utf-8 -*-
|
||||||
#
|
|
||||||
# For the full list of built-in configuration values, see the documentation:
|
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
|
||||||
|
|
||||||
# -- Project information -----------------------------------------------------
|
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
from recommonmark.parser import CommonMarkParser
|
||||||
|
import sphinx
|
||||||
|
|
||||||
project = 'coreboot'
|
# Get Sphinx version
|
||||||
copyright = 'CC-by 4.0 the coreboot project'
|
major = 0
|
||||||
author = 'the coreboot project'
|
minor = 0
|
||||||
|
patchlevel = 0
|
||||||
|
version = sphinx.__version__.split(".")
|
||||||
|
if len(version) > 1:
|
||||||
|
major = int(version[0])
|
||||||
|
minor = int(version[1])
|
||||||
|
if len(version) > 2:
|
||||||
|
patchlevel = int(version[2])
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['_templates']
|
||||||
|
|
||||||
|
# The suffix(es) of source filenames.
|
||||||
|
source_suffix = ['.md']
|
||||||
|
|
||||||
|
# The master toctree document.
|
||||||
|
master_doc = 'index'
|
||||||
|
|
||||||
|
# General information about the project.
|
||||||
|
project = u'coreboot'
|
||||||
|
copyright = u'CC-by 4.0 the coreboot project'
|
||||||
|
author = u'the coreboot project'
|
||||||
|
|
||||||
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
|
# |version| and |release|, also used in various other places throughout the
|
||||||
|
# built documents.
|
||||||
|
#
|
||||||
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = subprocess.check_output(('git', 'describe')).decode("utf-8")
|
release = subprocess.check_output(('git', 'describe')).decode("utf-8")
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = release.split("-")[0]
|
version = release.split("-")[0]
|
||||||
|
|
||||||
|
extensions = []
|
||||||
|
# Load recommonmark, supported since 1.8+
|
||||||
|
if major >= 2 or (major == 1 and minor >= 8):
|
||||||
|
extensions += ['recommonmark']
|
||||||
|
|
||||||
# -- General configuration ---------------------------------------------------
|
# Try to load DITAA
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
try:
|
||||||
|
import sphinxcontrib.ditaa
|
||||||
extensions = ["myst_parser"]
|
except ImportError:
|
||||||
|
print("Error: Please install sphinxcontrib.ditaa for ASCII art conversion\n")
|
||||||
myst_heading_anchors = 5
|
else:
|
||||||
myst_url_schemes = ["http", "https", "mailto", "ftp", "ircs"]
|
extensions += ['sphinxcontrib.ditaa']
|
||||||
|
|
||||||
templates_path = ['_templates']
|
|
||||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
|
||||||
|
|
||||||
# The name of the Pygments (syntax highlighting) style to use.
|
|
||||||
pygments_style = 'sphinx'
|
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
|
|
@ -38,11 +57,62 @@ pygments_style = 'sphinx'
|
||||||
# Usually you set "language" from the command line for these cases.
|
# Usually you set "language" from the command line for these cases.
|
||||||
language = 'en'
|
language = 'en'
|
||||||
|
|
||||||
# -- Options for HTML output -------------------------------------------------
|
# List of patterns, relative to source directory, that match files and
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
# directories to ignore when looking for source files.
|
||||||
|
# This patterns also effect to html_static_path and html_extra_path
|
||||||
|
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||||
|
|
||||||
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
|
# A list of ignored prefixes for module index sorting.
|
||||||
|
# modindex_common_prefix = []
|
||||||
|
|
||||||
|
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||||
|
# keep_warnings = False
|
||||||
|
|
||||||
|
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||||
|
todo_include_todos = False
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output ----------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
#
|
||||||
html_theme = 'sphinx_rtd_theme'
|
html_theme = 'sphinx_rtd_theme'
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
html_static_path = ['_static']
|
html_static_path = ['_static']
|
||||||
|
|
||||||
html_css_files = [
|
html_css_files = [
|
||||||
'theme_overrides.css', # override wide tables in RTD theme
|
'theme_overrides.css', # override wide tables in RTD theme
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Output file base name for HTML help builder.
|
||||||
|
htmlhelp_basename = 'corebootdoc'
|
||||||
|
|
||||||
|
enable_auto_toc_tree = True
|
||||||
|
|
||||||
|
class MyCommonMarkParser(CommonMarkParser):
|
||||||
|
# remove this hack once upstream RecommonMark supports inline code
|
||||||
|
def visit_code(self, mdnode):
|
||||||
|
from docutils import nodes
|
||||||
|
n = nodes.literal(mdnode.literal, mdnode.literal)
|
||||||
|
self.current_node.append(n)
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
from recommonmark.transform import AutoStructify
|
||||||
|
# Load recommonmark on old Sphinx
|
||||||
|
if major == 1 and minor < 8:
|
||||||
|
app.add_source_parser('.md', MyCommonMarkParser)
|
||||||
|
|
||||||
|
app.add_config_value('recommonmark_config', {
|
||||||
|
'enable_auto_toc_tree': True,
|
||||||
|
'enable_auto_doc_ref': False, # broken in Sphinx 1.6+
|
||||||
|
'enable_eval_rst': True,
|
||||||
|
'url_resolver': lambda url: '/' + url
|
||||||
|
}, True)
|
||||||
|
app.add_transform(AutoStructify)
|
||||||
|
|
|
||||||
|
|
@ -522,7 +522,7 @@ The preferred style for *long* (multi-line) comments is:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
/*
|
/*
|
||||||
* This is the preferred style for long multi-line
|
* This is the preferred style for multi-line
|
||||||
* comments in the coreboot source code.
|
* comments in the coreboot source code.
|
||||||
* Please use it consistently.
|
* Please use it consistently.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -304,7 +304,7 @@ would be a good reviewer, look in the MAINTAINERS file or git history of
|
||||||
the files that you’ve changed, and add those people.
|
the files that you’ve changed, and add those people.
|
||||||
|
|
||||||
* Familiarize yourself with the coreboot [commit message
|
* Familiarize yourself with the coreboot [commit message
|
||||||
guidelines](#commit-message-guidelines), before pushing
|
guidelines](https://www.coreboot.org/Git#Commit_messages), before pushing
|
||||||
patches. This will help to keep annoying requests to fix your commit
|
patches. This will help to keep annoying requests to fix your commit
|
||||||
message to a minimum.
|
message to a minimum.
|
||||||
|
|
||||||
|
|
@ -348,8 +348,8 @@ commit message itself:
|
||||||
* Tested-by:
|
* Tested-by:
|
||||||
* Reviewed-by:
|
* Reviewed-by:
|
||||||
|
|
||||||
The script `util/scripts/cross-repo-cherrypick` can be used to help
|
The script `util/gitconfig/rebase.sh` can be used to help automate this.
|
||||||
automate this. Other tags such as 'Commit-Queue' can simply be removed.
|
Other tags such as 'Commit-Queue' can simply be removed.
|
||||||
|
|
||||||
* Check if there's documentation that needs to be updated to remain current
|
* Check if there's documentation that needs to be updated to remain current
|
||||||
after your change. If there's no documentation for the part of coreboot
|
after your change. If there's no documentation for the part of coreboot
|
||||||
|
|
@ -395,8 +395,8 @@ Gerrit user roles
|
||||||
There are a few relevant roles a user can have on Gerrit:
|
There are a few relevant roles a user can have on Gerrit:
|
||||||
|
|
||||||
- The anonymous user can check out source code.
|
- The anonymous user can check out source code.
|
||||||
- A registered user can also comment and give "+1" code reviews.
|
- A registered user can also comment and give "+1" and "-1" code reviews.
|
||||||
- A reviewer can give "-1" and "+2" code reviews.
|
- A reviewer can also give "+2" code reviews.
|
||||||
- A core developer can also give "-2" (that is, blocking) code reviews
|
- A core developer can also give "-2" (that is, blocking) code reviews
|
||||||
and submit changes.
|
and submit changes.
|
||||||
|
|
||||||
|
|
@ -433,55 +433,8 @@ reversed after they come back.
|
||||||
Requests for clarification and suggestions for updates to these guidelines
|
Requests for clarification and suggestions for updates to these guidelines
|
||||||
should be sent to the coreboot mailing list at <coreboot@coreboot.org>.
|
should be sent to the coreboot mailing list at <coreboot@coreboot.org>.
|
||||||
|
|
||||||
Commit message guidelines
|
|
||||||
-------------------------
|
|
||||||
Git does not enforce a certain style for commit messages. For all aspects of
|
|
||||||
Git to work best with, it's important to follow these simple guidelines for
|
|
||||||
commit messages:
|
|
||||||
|
|
||||||
* The first line of the commit message consists of a short
|
|
||||||
(less than 65 characters, absolute maximum is 75) summary
|
|
||||||
* The second line is empty (no whitespace at all)
|
|
||||||
* The third and any following number of lines contains a longer description
|
|
||||||
of the commit as is necessary, including relevant background information
|
|
||||||
and quite possibly rationale for why the issue was solved in this particular
|
|
||||||
way. These lines should never be longer than 75 characters.
|
|
||||||
* The next line is empty (no whitespace at all)
|
|
||||||
* An optional TEST= line which describes the test that was done in order to
|
|
||||||
validate the patch
|
|
||||||
* An optional BUG= line to reference to a bug (of [coreboot's bug tracker] or any
|
|
||||||
other) this patch resolves
|
|
||||||
* The next line is empty if the optional lines are used
|
|
||||||
* A Change-Id: line to let Gerrit track this logical change
|
|
||||||
* A Signed-off-by: line according to [Signed-off-by policy](#sign-off-procedure)
|
|
||||||
|
|
||||||
Please do not create the Change-Id: and Signed-off-by: entries manually because
|
|
||||||
it is boring and error-prone. Instead, please install the commit-msg hook, e.g.
|
|
||||||
by running
|
|
||||||
```Bash
|
|
||||||
make gitconfig
|
|
||||||
```
|
|
||||||
in coreboot's top-level directory, and let the hook script do it for you.
|
|
||||||
And remember to always use
|
|
||||||
```Bash
|
|
||||||
git commit -s
|
|
||||||
```
|
|
||||||
to have git add your Signed-off-by: automatically.
|
|
||||||
|
|
||||||
When you write your commit message, please keep the following two hints in mind:
|
|
||||||
|
|
||||||
* If anyone involved in coreboot reads your comment in a year or so, they
|
|
||||||
shall still be able to understand what your commit is about, without the need
|
|
||||||
to analyze the code.
|
|
||||||
* Double-check that you are really committing what you think you are, e.g. by
|
|
||||||
typing the following in the top-level coreboot directory:
|
|
||||||
```Bash
|
|
||||||
git show
|
|
||||||
```
|
|
||||||
|
|
||||||
[ready changes]: https://review.coreboot.org/q/age:1d+project:coreboot+status:open+is:mergeable+label:All-Comments-Resolved%253Dok+label:Code-Review%253D2+-label:Code-Review%253C0+label:Verified%253D1+-label:Verified-1
|
[ready changes]: https://review.coreboot.org/q/age:1d+project:coreboot+status:open+is:mergeable+label:All-Comments-Resolved%253Dok+label:Code-Review%253D2+-label:Code-Review%253C0+label:Verified%253D1+-label:Verified-1
|
||||||
[Developer's Certificate of Origin 1.1]: https://developercertificate.org/
|
[Developer's Certificate of Origin 1.1]: https://developercertificate.org/
|
||||||
[Creative Commons Attribution-ShareAlike 2.5 License]: https://creativecommons.org/licenses/by-sa/2.5/
|
[Creative Commons Attribution-ShareAlike 2.5 License]: https://creativecommons.org/licenses/by-sa/2.5/
|
||||||
[this LKML thread]: https://lkml.org/lkml/2004/5/23/10
|
[this LKML thread]: https://lkml.org/lkml/2004/5/23/10
|
||||||
[SCO-Linux disputes]: https://en.wikipedia.org/wiki/SCO%E2%80%93Linux_disputes
|
[SCO-Linux disputes]: https://en.wikipedia.org/wiki/SCO%E2%80%93Linux_disputes
|
||||||
[coreboot's bug tracker]: https://ticket.coreboot.org/
|
|
||||||
|
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
# Git Commit messages
|
|
||||||
|
|
||||||
There are a number of different recommendations for git commit
|
|
||||||
messages, so this is another one.
|
|
||||||
|
|
||||||
It's expected that coreboot contributors already generally understand
|
|
||||||
the idea of writing good git commit messages, so this is not trying
|
|
||||||
to go over everything again. There are other tutorials that cover that.
|
|
||||||
|
|
||||||
- [Linux Kernel tip tree Handbook](https://www.kernel.org/doc/html/latest/process/maintainer-tip.html#patch-subject)
|
|
||||||
- [How to write a Git Commit Message](https://cbea.ms/git-commit/)
|
|
||||||
|
|
||||||
## Line length
|
|
||||||
|
|
||||||
- The subject line should be <= 65 characters, with an absolute maximum
|
|
||||||
of 72 characters
|
|
||||||
- Prose in the commit message should be <= 72 characters
|
|
||||||
- If reflowing prose to 72 characters can reduce the length of the
|
|
||||||
commit message by 2 or more lines, please reflow it. Using the entire
|
|
||||||
72 characters on a line when reasonable is recommended, but not
|
|
||||||
required.
|
|
||||||
- Non-prose text in the body in the commit message does not need to be
|
|
||||||
wrapped at 72 characters. Examples: URLs, compiler output, or poetry.
|
|
||||||
|
|
||||||
## Both Subject & body
|
|
||||||
|
|
||||||
- Use the present tense. (The for loop exits too early, so ...", not
|
|
||||||
"The for loop exited too early, so ...").
|
|
||||||
- When using acronyms, make sure they're explained in the commit
|
|
||||||
message itself or in the [acronyms list](https://doc.coreboot.org/acronyms.html).
|
|
||||||
|
|
||||||
## Commit message Subject Line
|
|
||||||
|
|
||||||
- Start the subject line with a prefix denoting the area of the change.
|
|
||||||
Often part of the path can be used by that. Looking through existing
|
|
||||||
commit messages summaries with `git log --oneline ...` gives a good
|
|
||||||
idea. Because this prefix takes space used by the rest of the subject,
|
|
||||||
it should be kept short while still uniquely describing the area.
|
|
||||||
- Don't include `src/`
|
|
||||||
- Use abbreviations where possible:
|
|
||||||
- mb: mainboard
|
|
||||||
- vc: vendorcode
|
|
||||||
- Don't end the subject line with a period.
|
|
||||||
- Use the imperative mood. ("Fix whitespace", not "whitespace fixes").
|
|
||||||
|
|
||||||
## Commit Message Body
|
|
||||||
|
|
||||||
- Make sure the problem being solved by the commit is described. While
|
|
||||||
it may be obvious to the committer, it may not be obvious to others.
|
|
||||||
- When referencing other commits use a 12 character hash and the subject
|
|
||||||
(e.g. `commit XXXXXXXXXXXX ("some commit")`). However, use `CB:XXXXX`
|
|
||||||
when referring to an open or abandoned change on Gerrit.
|
|
||||||
- When using a URL in a commit message, use archive.org when possible.
|
|
||||||
URLs often get changed or go stale, so this keeps them stable.
|
|
||||||
- Make sure that all changes in a patch are addressed in the commit
|
|
||||||
message.
|
|
||||||
- A TEST= tag is highly recommended, but not required. This lets people
|
|
||||||
know whether you tested it by booting the board or just by compiling.
|
|
||||||
- All but the most trivial of patches should generally have a body.
|
|
||||||
- A BUG= tag can be added when the author wants to indicate that the
|
|
||||||
patch is or is not related to a bug. This can be either in coreboot's
|
|
||||||
issue tracker, or a private issue tracker.
|
|
||||||
- `BUG=b:####` is used by the Google internal issue tracker.
|
|
||||||
- `BUG=chromium:####` indicates the Chromium public tracker at
|
|
||||||
https://issues.chromium.org/
|
|
||||||
- `BUG=CID ####` can be used to indicate coverity error fixes.
|
|
||||||
- `BUG=https://...` can be used to link directly to a public
|
|
||||||
tracker.
|
|
||||||
- The BRANCH= tag is used in cases where a patch needs to be added to a
|
|
||||||
specific downstream branch. This is never required by the coreboot
|
|
||||||
project.
|
|
||||||
|
|
||||||
## Footers
|
|
||||||
|
|
||||||
- The Signed-off-by line is required (Jenkins forces this).
|
|
||||||
- The Change ID is required (Gerrit forces this.)
|
|
||||||
- When adding a patch that has already gone through another git or
|
|
||||||
gerrit, the footers from those previous commits may be added, but
|
|
||||||
keep the list reasonable.
|
|
||||||
|
|
@ -1,29 +1,7 @@
|
||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
```{toctree}
|
* [Coding Style](coding_style.md)
|
||||||
:maxdepth: 1
|
* [Gerrit Guidelines](gerrit_guidelines.md)
|
||||||
|
* [Project Ideas](project_ideas.md)
|
||||||
Coding Style <coding_style.md>
|
* [Documentation Ideas](documentation_ideas.md)
|
||||||
Gerrit Guidelines <gerrit_guidelines.md>
|
* [Google Summer of Code](gsoc.md)
|
||||||
Commit Message Guidelines <git_commit_messages.md>
|
|
||||||
Project Ideas <project_ideas.md>
|
|
||||||
Documentation Ideas <documentation_ideas.md>
|
|
||||||
Google Summer of Code <gsoc.md>
|
|
||||||
```
|
|
||||||
|
|
||||||
The coreboot project uses the Developer Certificate of Origin as its
|
|
||||||
policy of accepting contributions. As such, a submitter bears the burden
|
|
||||||
that they have all necessary rights to submit their contribution to the
|
|
||||||
project under the project's licenses as appropriate. Violations of third
|
|
||||||
party rights will lead to the code's removal or replacement as suitable
|
|
||||||
to bring the project back into compliance.
|
|
||||||
|
|
||||||
This applies no matter under which circumstances a contribution has been
|
|
||||||
created: legal frameworks, work contracts, Generative Artificial
|
|
||||||
Intelligence ("AI") tooling, or other aspects that may affect the
|
|
||||||
ownership and copyright status of a contribution are outside the
|
|
||||||
project's control.
|
|
||||||
|
|
||||||
See the [Sign-off procedure] for more information.
|
|
||||||
|
|
||||||
[Sign-off procedure]: gerrit_guidelines.md#sign-off-procedure
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ sealings are sent via encrypted email.
|
||||||
|
|
||||||
### NovaCustom laptops
|
### NovaCustom laptops
|
||||||
|
|
||||||
[NovaCustom](https://novacustom.com) sells configurable laptops with
|
[NovaCustom](https://configurelaptop.eu/) sells configurable laptops with
|
||||||
[Dasharo](https://dasharo.com/) coreboot based firmware on board, maintained by
|
[Dasharo](https://dasharo.com/) coreboot based firmware on board, maintained by
|
||||||
[3mdeb](https://3mdeb.com/). NovaCustom offers full GNU/Linux and Microsoft
|
[3mdeb](https://3mdeb.com/). NovaCustom offers full GNU/Linux and Microsoft
|
||||||
Windows compatibility. NovaCustom ensures security updates via fwupd for 5 years
|
Windows compatibility. NovaCustom ensures security updates via fwupd for 5 years
|
||||||
|
|
|
||||||
|
|
@ -1,387 +0,0 @@
|
||||||
# ACPI Active Cooling with Five-Level Fan Control
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
This document describes an ACPI-based thermal management pattern used across multiple coreboot mainboards. The implementation uses ACPI thermal zones with active cooling policies to control fan speed based on CPU temperature through a five-level power resource state machine.
|
|
||||||
|
|
||||||
This pattern is particularly prevalent on Intel-based mainboards using SuperIO environmental controllers for fan PWM control.
|
|
||||||
|
|
||||||
## Mainboards Using This Pattern
|
|
||||||
|
|
||||||
The following mainboards implement this five-level ACPI fan control pattern:
|
|
||||||
|
|
||||||
### Google Chromebooks
|
|
||||||
- **google/beltino** - Haswell Chromebox
|
|
||||||
- All variants (mccloud, monroe, panther, tricky, zako) use a single implementation
|
|
||||||
- **google/jecht** - Broadwell Chromebox
|
|
||||||
- Each variant (jecht, rikku, guado, tidus) has a unique implementation
|
|
||||||
|
|
||||||
### Samsung
|
|
||||||
- **samsung/stumpy** - Sandy Bridge Chromebox
|
|
||||||
|
|
||||||
### Intel Reference Boards
|
|
||||||
- **intel/wtm2** - Haswell ULT reference board
|
|
||||||
- **intel/baskingridge** - Haswell desktop reference board
|
|
||||||
- **intel/emeraldlake2** - Ivy Bridge reference board
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
### Hardware Components
|
|
||||||
|
|
||||||
Common hardware elements across implementations:
|
|
||||||
|
|
||||||
- **Temperature Sensor**: SuperIO TMPIN3 reads CPU temperature via PECI (Platform Environment Control Interface)
|
|
||||||
- **Fan Controller**: SuperIO Environmental Controller (ENVC) with PWM output
|
|
||||||
- Fan2 (F2PS) on Google Chromebooks
|
|
||||||
- Fan3 (F3PS) on Intel/Samsung boards
|
|
||||||
- **CPU**: Provides temperature data as an offset from Tj_max (maximum junction temperature)
|
|
||||||
|
|
||||||
### ACPI Components
|
|
||||||
|
|
||||||
- **Thermal Zone**: `\_TZ.THRM` - Main thermal management zone
|
|
||||||
- **Fan Devices**: `FAN0` through `FAN4` - Five fan speed levels
|
|
||||||
- **Power Resources**: `FNP0` through `FNP4` - Control fan state transitions
|
|
||||||
- **Active Cooling Levels**: `_AC0` through `_AC4` - Temperature thresholds for each fan level
|
|
||||||
|
|
||||||
## Fan Speed Levels
|
|
||||||
|
|
||||||
The system implements **5 fan speed levels** (0-4), where:
|
|
||||||
|
|
||||||
- **Level 0**: Maximum fan speed (highest cooling, activated at highest temperature)
|
|
||||||
- **Level 1**: High fan speed
|
|
||||||
- **Level 2**: Medium fan speed
|
|
||||||
- **Level 3**: Low fan speed
|
|
||||||
- **Level 4**: Minimum fan speed (idle/baseline cooling, default state)
|
|
||||||
|
|
||||||
The system starts at **Level 4** (minimum speed) and increases to lower-numbered levels as temperature rises.
|
|
||||||
|
|
||||||
## Temperature Management
|
|
||||||
|
|
||||||
### Temperature Reading Process
|
|
||||||
|
|
||||||
1. **Raw PECI Reading**: Read from `\_SB.PCI0.LPCB.SIO.ENVC.TIN3`
|
|
||||||
- Returns a value representing offset from Tj_max
|
|
||||||
- Value 0x80 indicates "no reading available"
|
|
||||||
- Values 0 or 255 are invalid
|
|
||||||
|
|
||||||
2. **Temperature Calculation**:
|
|
||||||
```
|
|
||||||
actual_temperature = Tj_max - (255 - raw_value)
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Conversion to ACPI Format**: Convert from Celsius to deci-Kelvin:
|
|
||||||
```
|
|
||||||
deci_kelvin = (celsius * 10) + 2732
|
|
||||||
```
|
|
||||||
|
|
||||||
### Critical Temperature Handling
|
|
||||||
|
|
||||||
Most implementations include safety logic in the `_TMP` method:
|
|
||||||
- If temperature reaches `\TMAX` (Tj_max), logs a critical event
|
|
||||||
- Waits 1 second for sensor re-poll
|
|
||||||
- Re-reads temperature to confirm
|
|
||||||
- Reports the current temperature to the OS
|
|
||||||
|
|
||||||
### Temperature Thresholds
|
|
||||||
|
|
||||||
Thresholds are defined in board-specific headers (typically `thermal.h`):
|
|
||||||
|
|
||||||
- `FAN0_THRESHOLD_ON/OFF` - Trigger points for maximum fan speed
|
|
||||||
- `FAN1_THRESHOLD_ON/OFF` - Trigger points for high fan speed
|
|
||||||
- `FAN2_THRESHOLD_ON/OFF` - Trigger points for medium fan speed
|
|
||||||
- `FAN3_THRESHOLD_ON/OFF` - Trigger points for low fan speed
|
|
||||||
- `FAN4_PWM` - PWM value for minimum fan speed
|
|
||||||
|
|
||||||
Each level has hysteresis (different ON/OFF thresholds) to prevent rapid cycling.
|
|
||||||
|
|
||||||
## Active Cooling Implementation
|
|
||||||
|
|
||||||
### Active Cooling Methods (`_ACx`)
|
|
||||||
|
|
||||||
Each `_ACx` method returns a temperature threshold:
|
|
||||||
- When system temperature **exceeds** the threshold, the OS activates the corresponding fan level
|
|
||||||
- When temperature **falls below** the threshold, the OS may deactivate that level
|
|
||||||
|
|
||||||
**Hysteresis Logic**:
|
|
||||||
```
|
|
||||||
Method (_AC0) {
|
|
||||||
If (\FLVL <= 0) {
|
|
||||||
Return (CTOK (FAN0_THRESHOLD_OFF)) // Higher temp to turn off
|
|
||||||
} Else {
|
|
||||||
Return (CTOK (FAN0_THRESHOLD_ON)) // Lower temp to turn on
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This prevents oscillation by requiring different temperatures to activate vs. deactivate a fan level.
|
|
||||||
|
|
||||||
### Active Cooling Lists (`_ALx`)
|
|
||||||
|
|
||||||
Each `_ALx` associates a cooling threshold with a fan device:
|
|
||||||
```
|
|
||||||
Name (_AL0, Package () { FAN0 }) // FAN0 activated at _AC0 threshold
|
|
||||||
Name (_AL1, Package () { FAN1 }) // FAN1 activated at _AC1 threshold
|
|
||||||
Name (_AL2, Package () { FAN2 }) // FAN2 activated at _AC2 threshold
|
|
||||||
Name (_AL3, Package () { FAN3 }) // FAN3 activated at _AC3 threshold
|
|
||||||
Name (_AL4, Package () { FAN4 }) // FAN4 activated at _AC4 threshold
|
|
||||||
```
|
|
||||||
|
|
||||||
## Power Resource State Machine
|
|
||||||
|
|
||||||
Each fan level has an associated power resource (`FNP0` through `FNP4`) that manages state transitions.
|
|
||||||
|
|
||||||
### State Transitions
|
|
||||||
|
|
||||||
**FNP0-FNP3** (Levels 0-3):
|
|
||||||
- `_STA`: Returns 1 (ON) if `\FLVL <= level`, else 0 (OFF)
|
|
||||||
- `_ON`: Transitions **to** this level from a higher-numbered level
|
|
||||||
- `_OFF`: Transitions **away** from this level to the next higher-numbered level
|
|
||||||
|
|
||||||
Example for FNP0 (maximum cooling):
|
|
||||||
```
|
|
||||||
PowerResource (FNP0, 0, 0) {
|
|
||||||
Method (_STA) {
|
|
||||||
If (\FLVL <= 0) { Return (1) } // Active if at max cooling
|
|
||||||
Else { Return (0) }
|
|
||||||
}
|
|
||||||
Method (_ON) {
|
|
||||||
If (!_STA ()) { // If not already active
|
|
||||||
\FLVL = 0 // Set to max cooling
|
|
||||||
\_SB.PCI0.LPCB.SIO.ENVC.F2PS = FAN0_PWM // Set fan PWM
|
|
||||||
Notify (\_TZ.THRM, 0x81) // Notify thermal zone
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Method (_OFF) {
|
|
||||||
If (_STA ()) { // If currently active
|
|
||||||
\FLVL = 1 // Transition to level 1
|
|
||||||
\_SB.PCI0.LPCB.SIO.ENVC.F2PS = FAN1_PWM // Set corresponding PWM
|
|
||||||
Notify (\_TZ.THRM, 0x81) // Notify thermal zone
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**FNP4** (Minimum cooling - Level 4):
|
|
||||||
- `_STA`: Returns 1 if `\FLVL <= 4` (always true in normal operation)
|
|
||||||
- `_ON`: Transitions to minimum cooling state
|
|
||||||
- `_OFF`: **No-op** - This is the minimum state, cannot transition lower
|
|
||||||
|
|
||||||
### Critical: FNP4._OFF Must Be a No-Op
|
|
||||||
|
|
||||||
This is **essential for Windows compatibility**:
|
|
||||||
|
|
||||||
**Problem**: Early implementations had `_OFF` setting `\FLVL = 4` and PWM values, identical to `_ON`. This violated ACPI power resource requirements:
|
|
||||||
- After `_ON` is called, `_STA` must eventually return 1 (ON)
|
|
||||||
- After `_OFF` is called, `_STA` must eventually return 0 (OFF)
|
|
||||||
|
|
||||||
Since both methods resulted in `\FLVL = 4`, and `_STA` returns 1 when `\FLVL <= 4`, the power resource could never properly transition to OFF state.
|
|
||||||
|
|
||||||
**Solution**: Make `_OFF` a no-op since FAN4 is the minimum cooling state:
|
|
||||||
```
|
|
||||||
PowerResource (FNP4, 0, 0) {
|
|
||||||
Method (_STA) {
|
|
||||||
If (\FLVL <= 4) { Return (1) }
|
|
||||||
Else { Return (0) }
|
|
||||||
}
|
|
||||||
Method (_ON) {
|
|
||||||
If (!_STA ()) {
|
|
||||||
\FLVL = 4
|
|
||||||
\_SB.PCI0.LPCB.SIO.ENVC.F2PS = FAN4_PWM
|
|
||||||
Notify (\_TZ.THRM, 0x81)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Method (_OFF) {
|
|
||||||
// FAN4 is the minimum cooling state (idle/lowest fan speed)
|
|
||||||
// There is no lower state to transition to, so _OFF is a no-op
|
|
||||||
// to maintain proper ACPI power resource state machine semantics
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This maintains proper ACPI state machine semantics and ensures Windows compatibility while maintaining Linux compatibility.
|
|
||||||
|
|
||||||
## Passive Cooling
|
|
||||||
|
|
||||||
In addition to active (fan-based) cooling, most implementations support passive cooling:
|
|
||||||
|
|
||||||
- `_PSV`: Returns passive cooling threshold temperature
|
|
||||||
- `_PSL`: Returns list of processors to throttle
|
|
||||||
- `_TC1`, `_TC2`: Thermal constants for passive cooling algorithm
|
|
||||||
- `_TSP`: Thermal sampling period (typically 20 deciseconds = 2 seconds)
|
|
||||||
|
|
||||||
When temperature exceeds `_PSV` threshold, the OS throttles CPUs listed in `_PSL` to reduce heat generation.
|
|
||||||
|
|
||||||
## Polling and Notification
|
|
||||||
|
|
||||||
- `_TZP`: Thermal zone polling period (typically 100 deciseconds = 10 seconds)
|
|
||||||
- OS polls `_TMP` at this interval to check temperature
|
|
||||||
|
|
||||||
- `Notify (\_TZ.THRM, 0x81)`: Thermal zone change notification
|
|
||||||
- Sent whenever fan level changes
|
|
||||||
- Tells OS to re-evaluate thermal zone immediately
|
|
||||||
|
|
||||||
## Initialization
|
|
||||||
|
|
||||||
The `_INI` method runs when the thermal zone is initialized:
|
|
||||||
|
|
||||||
```
|
|
||||||
Method (_INI) {
|
|
||||||
\FLVL = 4 // Start at minimum cooling
|
|
||||||
\_SB.PCI0.LPCB.SIO.ENVC.F2PS = FAN4_PWM // Set initial fan PWM
|
|
||||||
Notify (\_TZ.THRM, 0x81) // Initial notification
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Operating System Interaction
|
|
||||||
|
|
||||||
### Thermal Policy Flow
|
|
||||||
|
|
||||||
1. **OS boots** → Executes `_INI` → Fan starts at Level 4
|
|
||||||
2. **OS polls `_TMP`** periodically → Gets current temperature
|
|
||||||
3. **Temperature rises** → Exceeds `_AC3` threshold
|
|
||||||
4. **OS calls `FAN3._ON`** → Power resource FNP3 activated → `\FLVL = 3`
|
|
||||||
5. **Temperature continues rising** → Exceeds `_AC2` threshold
|
|
||||||
6. **OS calls `FAN2._ON`** → Power resource FNP2 activated → `\FLVL = 2`
|
|
||||||
7. **Temperature drops** → Falls below `_AC2` threshold
|
|
||||||
8. **OS calls `FAN2._OFF`** → `\FLVL = 3` → Returns to Level 3
|
|
||||||
9. **Cycle continues** based on temperature changes
|
|
||||||
|
|
||||||
### Critical Temperature
|
|
||||||
|
|
||||||
If temperature reaches `_CRT` threshold:
|
|
||||||
- OS initiates emergency shutdown
|
|
||||||
- Prevents hardware damage from overheating
|
|
||||||
|
|
||||||
## Global Variables
|
|
||||||
|
|
||||||
Standard variables used across implementations:
|
|
||||||
|
|
||||||
- `\FLVL`: Current fan level (0-4)
|
|
||||||
- `\TMAX`: Maximum junction temperature (Tj_max)
|
|
||||||
- `\TCRT`: Critical shutdown temperature
|
|
||||||
- `\TPSV`: Passive cooling threshold temperature
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
Fan thresholds and PWM values are defined in board-specific headers, typically:
|
|
||||||
```
|
|
||||||
src/mainboard/<vendor>/<board>/include/thermal.h
|
|
||||||
```
|
|
||||||
or
|
|
||||||
```
|
|
||||||
src/mainboard/<vendor>/<board>/variants/<variant>/include/variant/thermal.h
|
|
||||||
```
|
|
||||||
|
|
||||||
Example configuration:
|
|
||||||
```c
|
|
||||||
#define FAN0_THRESHOLD_ON 75 // Temperature to activate max fan (°C)
|
|
||||||
#define FAN0_THRESHOLD_OFF 65 // Temperature to deactivate max fan (°C)
|
|
||||||
#define FAN0_PWM 0xFF // PWM duty cycle value (max)
|
|
||||||
|
|
||||||
#define FAN1_THRESHOLD_ON 65
|
|
||||||
#define FAN1_THRESHOLD_OFF 55
|
|
||||||
#define FAN1_PWM 0xC0
|
|
||||||
|
|
||||||
#define FAN2_THRESHOLD_ON 55
|
|
||||||
#define FAN2_THRESHOLD_OFF 45
|
|
||||||
#define FAN2_PWM 0x80
|
|
||||||
|
|
||||||
#define FAN3_THRESHOLD_ON 45
|
|
||||||
#define FAN3_THRESHOLD_OFF 35
|
|
||||||
#define FAN3_PWM 0x40
|
|
||||||
|
|
||||||
#define FAN4_PWM 0x20 // Idle fan speed
|
|
||||||
```
|
|
||||||
|
|
||||||
## Implementation Variations
|
|
||||||
|
|
||||||
While the core pattern is consistent, there are some variations:
|
|
||||||
|
|
||||||
### PWM Output Selection
|
|
||||||
- **Google boards**: Use Fan2 PWM (`F2PS`)
|
|
||||||
- **Intel/Samsung boards**: Use Fan3 PWM (`F3PS`)
|
|
||||||
|
|
||||||
### Guard Checks
|
|
||||||
Some implementations wrap state changes with `_STA()` checks:
|
|
||||||
```
|
|
||||||
Method (_ON) {
|
|
||||||
If (!_STA ()) { // Only change state if not already active
|
|
||||||
// ... state change
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Others omit the guard and always perform the state change.
|
|
||||||
|
|
||||||
### Temperature Reading
|
|
||||||
- Most implementations read from SuperIO TMPIN3 via PECI
|
|
||||||
- Some (like intel/wtm2) use simplified stub implementations for reference
|
|
||||||
|
|
||||||
### Dynamic Thermal Tables
|
|
||||||
The google/jecht/tidus variant includes multiple thermal tables that can be switched based on system temperature sensors, allowing more sophisticated thermal management.
|
|
||||||
|
|
||||||
## Compatibility Notes
|
|
||||||
|
|
||||||
### Linux
|
|
||||||
- More lenient ACPI parser
|
|
||||||
- Tolerates minor state machine violations
|
|
||||||
- Worked with buggy FNP4._OFF implementations
|
|
||||||
|
|
||||||
### Windows
|
|
||||||
- Stricter ACPI compliance checking
|
|
||||||
- Requires proper power resource state machine behavior
|
|
||||||
- **Requires the FNP4._OFF no-op fix** to function correctly
|
|
||||||
- May disable thermal zone entirely if ACPI violations detected
|
|
||||||
|
|
||||||
## Debugging
|
|
||||||
|
|
||||||
To debug fan control issues:
|
|
||||||
|
|
||||||
1. **Check ACPI errors**: Look for thermal zone errors in OS logs
|
|
||||||
- Linux: `dmesg | grep -i acpi` or check `/sys/class/thermal/`
|
|
||||||
- Windows: Event Viewer → System → ACPI errors
|
|
||||||
|
|
||||||
2. **Monitor temperature**: Use OS tools to check `_TMP` readings
|
|
||||||
- Linux: `/sys/class/thermal/thermal_zone*/temp`
|
|
||||||
- Windows: HWiNFO64, HWMonitor
|
|
||||||
|
|
||||||
3. **Check fan level**: Monitor `\FLVL` value (ACPI debugger or custom logging)
|
|
||||||
|
|
||||||
4. **Verify thresholds**: Ensure threshold values are appropriate for the hardware
|
|
||||||
|
|
||||||
5. **Test state transitions**: Verify each fan level activates at correct temperature
|
|
||||||
|
|
||||||
6. **ACPI table inspection**: Decompile DSDT/SSDT tables with `acpidump` and `iasl` to verify implementation
|
|
||||||
|
|
||||||
## Implementation Checklist
|
|
||||||
|
|
||||||
When implementing this pattern on a new board:
|
|
||||||
|
|
||||||
- [ ] Define all 5 fan threshold pairs (ON/OFF) with appropriate hysteresis
|
|
||||||
- [ ] Define PWM values for all 5 fan levels
|
|
||||||
- [ ] Implement temperature sensor reading (typically PECI via SuperIO)
|
|
||||||
- [ ] Implement CTOK conversion method (°C to deci-Kelvin)
|
|
||||||
- [ ] Create all 5 PowerResource objects (FNP0-FNP4)
|
|
||||||
- [ ] **Critical**: Ensure FNP4._OFF is a no-op (not setting state)
|
|
||||||
- [ ] Create all 5 Fan Device objects (FAN0-FAN4) with correct `_PR0` references
|
|
||||||
- [ ] Implement _ACx methods with hysteresis logic
|
|
||||||
- [ ] Define _ALx packages linking to fan devices
|
|
||||||
- [ ] Implement _INI to set initial state
|
|
||||||
- [ ] Implement _TMP with error handling
|
|
||||||
- [ ] Define _CRT, _PSV, _PSL for critical/passive cooling
|
|
||||||
- [ ] Set appropriate _TZP polling interval
|
|
||||||
- [ ] Test on both Linux and Windows
|
|
||||||
|
|
||||||
## References
|
|
||||||
|
|
||||||
- [ACPI Specification 6.5 - Thermal Management](https://uefi.org/specs/ACPI/6.5/)
|
|
||||||
- [ACPI Specification - ThermalZone Objects](https://uefi.org/specs/ACPI/6.5/11_Thermal_Management.html)
|
|
||||||
- [ACPI Specification - PowerResource Objects](https://uefi.org/specs/ACPI/6.5/07_Power_and_Performance_Mgmt.html#power-resources)
|
|
||||||
- Intel PECI Specification
|
|
||||||
- SuperIO vendor datasheets (ITE, Nuvoton, Winbond, etc.)
|
|
||||||
|
|
||||||
## See Also
|
|
||||||
|
|
||||||
- [Intel DPTF](dptf.md) - More sophisticated Intel Dynamic Platform and Thermal Framework
|
|
||||||
- [ACPI GPIO Documentation](../acpi/gpio.md)
|
|
||||||
|
|
||||||
|
|
@ -1,297 +0,0 @@
|
||||||
# CFR - coreboot form representation
|
|
||||||
|
|
||||||
This documents the API exposed by coreboot to be consumed by
|
|
||||||
loaded OS image or payload.
|
|
||||||
|
|
||||||
## Problem Statement
|
|
||||||
|
|
||||||
As per coreboot design there's no UI present to change firmware
|
|
||||||
related options like "Hyper-Theading Enable". There's no way of
|
|
||||||
knowing what options are supported, if they are supported in the
|
|
||||||
current configuration and what they do.
|
|
||||||
|
|
||||||
The `USE_OPTION_TABLE` Kconfig allows to integrate a list of
|
|
||||||
mainboard specific options into coreboot tables when the option
|
|
||||||
API is using the *CMOS NVRAM*. It has no meaning if another option
|
|
||||||
API is being used.
|
|
||||||
|
|
||||||
## Design Proposal
|
|
||||||
|
|
||||||
Propose a new coreboot table that is independent from the option
|
|
||||||
backend. The coreboot table is generated from coreboot ramstage
|
|
||||||
code.
|
|
||||||
|
|
||||||
Every possible boot option is described by its name, the user
|
|
||||||
visible name, a help text, a default value and status flags.
|
|
||||||
All strings are in ASCII.
|
|
||||||
|
|
||||||
The boot options are grouped into forms, where each form hold
|
|
||||||
one or more options. Boot options that are not used in the current
|
|
||||||
boot flow, and are never reachable should be marked as hidden.
|
|
||||||
Dependecies between options can be defined in the code and should
|
|
||||||
be evaluated by the CFR parser/UI.
|
|
||||||
|
|
||||||
A boot option can be one of the following types:
|
|
||||||
- boolean
|
|
||||||
- number
|
|
||||||
- enum
|
|
||||||
- string
|
|
||||||
|
|
||||||
All of the information is *Position Independent Data*. That is, it is
|
|
||||||
safe to relocate any of the information without its meaning/correctness
|
|
||||||
changing.
|
|
||||||
|
|
||||||
CFR records form a tree structure. Every record starts with a `tag`
|
|
||||||
and a `size` field as generic header:
|
|
||||||
|
|
||||||
```C
|
|
||||||
struct __packed lb_cfr_header {
|
|
||||||
uint32_t tag;
|
|
||||||
uint32_t size;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
The size of a record includes the size of its own fields plus the size of all
|
|
||||||
child records. A record can have none or multiple child records.
|
|
||||||
The record `tag` must be known by the parser to parse the record and its
|
|
||||||
sub records. If it is not known to the parser it can simply skip it by
|
|
||||||
jumping `size` bytes forward.
|
|
||||||
|
|
||||||
The coreboot table containing the CFR tree has the tag `LB_TAG_CFR`.
|
|
||||||
|
|
||||||
The public API can be found in
|
|
||||||
`src/commonlib/include/commonlib/cfr.h` and
|
|
||||||
`src/commonlib/include/commonlib/coreboot_tables.h`.
|
|
||||||
|
|
||||||
## Implementation design
|
|
||||||
### Tags
|
|
||||||
Tags identify the structure defined in `src/commonlib/include/commonlib/cfr.h`.
|
|
||||||
Every struct might be immediately followed by additional structs (so called
|
|
||||||
sub nodes), having their own tag and size field. The sum of all sub nodes size
|
|
||||||
fields plus the size of the struct itself equals the size field.
|
|
||||||
|
|
||||||
* CFR_TAG_OPTION_FORM
|
|
||||||
|
|
||||||
Used in `struct lb_cfr_option_form` to describe a group of options. Every
|
|
||||||
sub node is one option that should be displayed in the order found in
|
|
||||||
memory.
|
|
||||||
|
|
||||||
Allowed sub nodes:
|
|
||||||
- `CFR_TAG_OPTION_ENUM`
|
|
||||||
- `CFR_TAG_OPTION_NUMBER`
|
|
||||||
- `CFR_TAG_OPTION_BOOL`
|
|
||||||
- `CFR_TAG_OPTION_VARCHAR`
|
|
||||||
- `CFR_TAG_OPTION_FORM`
|
|
||||||
- `CFR_TAG_OPTION_COMMENT`
|
|
||||||
- `CFR_TAG_VARCHAR_UI_NAME`
|
|
||||||
|
|
||||||
Required sub nodes:
|
|
||||||
- `CFR_TAG_VARCHAR_UI_NAME`
|
|
||||||
|
|
||||||
* CFR_TAG_ENUM_VALUE
|
|
||||||
|
|
||||||
Used in `struct lb_cfr_enum_value` to describe a numeric value to be
|
|
||||||
used in a parent `CFR_TAG_OPTION_ENUM`.
|
|
||||||
|
|
||||||
Allowed sub nodes:
|
|
||||||
- `CFR_TAG_VARCHAR_UI_NAME`
|
|
||||||
|
|
||||||
Required sub nodes:
|
|
||||||
- `CFR_TAG_VARCHAR_UI_NAME`
|
|
||||||
|
|
||||||
* CFR_TAG_OPTION_ENUM
|
|
||||||
|
|
||||||
Used in `struct lb_cfr_numeric_option` to describe a numeric variable with
|
|
||||||
a predefined selection of possible values in the referenced variable.
|
|
||||||
|
|
||||||
Allowed sub nodes:
|
|
||||||
- `CFR_TAG_VARCHAR_OPT_NAME`
|
|
||||||
- `CFR_TAG_VARCHAR_UI_NAME`
|
|
||||||
- `CFR_TAG_ENUM_VALUE`
|
|
||||||
- `CFR_TAG_VARCHAR_UI_HELPTEXT`
|
|
||||||
|
|
||||||
Required sub nodes:
|
|
||||||
- `CFR_TAG_VARCHAR_OPT_NAME`
|
|
||||||
- `CFR_TAG_VARCHAR_UI_NAME`
|
|
||||||
- `CFR_TAG_ENUM_VALUE`
|
|
||||||
|
|
||||||
* CFR_TAG_OPTION_NUMBER
|
|
||||||
|
|
||||||
Used in `struct lb_cfr_numeric_option` to describe a numeric variable with
|
|
||||||
any possible value in the referenced variable.
|
|
||||||
|
|
||||||
Allowed sub nodes:
|
|
||||||
- `CFR_TAG_VARCHAR_OPT_NAME`
|
|
||||||
- `CFR_TAG_VARCHAR_UI_NAME`
|
|
||||||
- `CFR_TAG_VARCHAR_UI_HELPTEXT`
|
|
||||||
|
|
||||||
Required sub nodes:
|
|
||||||
- `CFR_TAG_VARCHAR_OPT_NAME`
|
|
||||||
- `CFR_TAG_VARCHAR_UI_NAME`
|
|
||||||
|
|
||||||
* CFR_TAG_OPTION_BOOL
|
|
||||||
|
|
||||||
Used in `struct lb_cfr_numeric_option` to describe a numeric variable with
|
|
||||||
the possible values [0, 1] in the referenced variable.
|
|
||||||
|
|
||||||
Allowed sub nodes:
|
|
||||||
- `CFR_TAG_VARCHAR_OPT_NAME`
|
|
||||||
- `CFR_TAG_VARCHAR_UI_NAME`
|
|
||||||
- `CFR_TAG_VARCHAR_UI_HELPTEXT`
|
|
||||||
|
|
||||||
Required sub nodes:
|
|
||||||
- `CFR_TAG_VARCHAR_OPT_NAME`
|
|
||||||
- `CFR_TAG_VARCHAR_UI_NAME`
|
|
||||||
|
|
||||||
* CFR_TAG_OPTION_VARCHAR
|
|
||||||
|
|
||||||
Used in `struct lb_cfr_varchar_option` to describe an ASCII string
|
|
||||||
stored in the referenced variable.
|
|
||||||
|
|
||||||
*Example:* Linux kernel cmdline.
|
|
||||||
|
|
||||||
Allowed sub nodes:
|
|
||||||
- `CFR_TAG_VARCHAR_DEF_VALUE`
|
|
||||||
- `CFR_TAG_VARCHAR_OPT_NAME`
|
|
||||||
- `CFR_TAG_VARCHAR_UI_NAME`
|
|
||||||
- `CFR_TAG_VARCHAR_UI_HELPTEXT`
|
|
||||||
|
|
||||||
Required sub nodes:
|
|
||||||
- `CFR_TAG_VARCHAR_DEF_VALUE`
|
|
||||||
- `CFR_TAG_VARCHAR_OPT_NAME`
|
|
||||||
- `CFR_TAG_VARCHAR_UI_NAME`
|
|
||||||
|
|
||||||
* CFR_TAG_OPTION_COMMENT
|
|
||||||
|
|
||||||
Used in `struct lb_cfr_option_comment` to describe an ASCII string visible
|
|
||||||
to the user, but doesn't reference a variable. Informal use only.
|
|
||||||
|
|
||||||
Allowed sub nodes:
|
|
||||||
- `CFR_TAG_VARCHAR_UI_NAME`
|
|
||||||
- `CFR_TAG_VARCHAR_UI_HELPTEXT`
|
|
||||||
|
|
||||||
Required sub nodes:
|
|
||||||
- `CFR_TAG_VARCHAR_UI_NAME`
|
|
||||||
|
|
||||||
* CFR_TAG_VARCHAR_OPT_NAME
|
|
||||||
|
|
||||||
Used in `struct lb_cfr_varbinary` to describe the option name used by
|
|
||||||
coreboot's code. It thus must match what is used in code by
|
|
||||||
`get_uint_option()`.
|
|
||||||
|
|
||||||
Is not user visible.
|
|
||||||
|
|
||||||
* CFR_TAG_VARCHAR_UI_NAME
|
|
||||||
|
|
||||||
Used in `struct lb_cfr_varbinary`
|
|
||||||
|
|
||||||
User visible name of the option.
|
|
||||||
|
|
||||||
* CFR_TAG_VARCHAR_UI_HELPTEXT
|
|
||||||
|
|
||||||
Used in `struct lb_cfr_varbinary`
|
|
||||||
|
|
||||||
Optional user visible description what is changed by this option.
|
|
||||||
|
|
||||||
* CFR_TAG_VARCHAR_DEF_VALUE
|
|
||||||
|
|
||||||
Used in `struct lb_cfr_varbinary`
|
|
||||||
|
|
||||||
Default value in case the variable is not present.
|
|
||||||
|
|
||||||
### Flags
|
|
||||||
|
|
||||||
The optional flags describe the visibilty of the option and the
|
|
||||||
effect on the non-volatile variable.
|
|
||||||
|
|
||||||
* `CFR_OPTFLAG_READONLY`
|
|
||||||
|
|
||||||
Prevents writes to the variable.
|
|
||||||
|
|
||||||
* `CFR_OPTFLAG_INACTIVE`
|
|
||||||
|
|
||||||
Implies `READONLY`. The option is visible, but cannot be modified
|
|
||||||
because one of the dependencies are not given. However there's a
|
|
||||||
possibility to enable the option by changing runtime configuration.
|
|
||||||
|
|
||||||
*For example:* Setting SATA mode, but SATA is globally disabled.
|
|
||||||
|
|
||||||
* `CFR_OPTFLAG_SUPPRESS`
|
|
||||||
|
|
||||||
Runtime code sets this flag to indicate that the option has no effect
|
|
||||||
and is never reachable, not even by changing runtime configuration.
|
|
||||||
This option is never shown in the UI.
|
|
||||||
|
|
||||||
* `CFR_OPTFLAG_VOLATILE`
|
|
||||||
|
|
||||||
Implies `READONLY`.
|
|
||||||
The option is not backed by a non-volatile variable. This is useful
|
|
||||||
to display the current state of a specific component, a dependency or
|
|
||||||
a serial number. This information could be passed in a new coreboot
|
|
||||||
table, but it not useful other than to be shown at this spot in the
|
|
||||||
UI.
|
|
||||||
|
|
||||||
* `CFR_OPTFLAG_RUNTIME`
|
|
||||||
|
|
||||||
The option is allowed to be changed by a post payload entity. On UEFI
|
|
||||||
this sets the `EFI_VARIABLE_RUNTIME_ACCESS` attribute.
|
|
||||||
It is out of scope of this specification how non runtime variables
|
|
||||||
are protected after the payload has hand over control.
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
To display a boolean option with the label `Boolean`, that default value
|
|
||||||
is `true`, on a form called `test`, that modifies the variable `First`
|
|
||||||
the following structure will be generated:
|
|
||||||
|
|
||||||
```
|
|
||||||
struct lb_cfr_option_form {
|
|
||||||
uint32_t tag; = CFR_TAG_OPTION_FORM
|
|
||||||
uint32_t size; = sizeof(struct lb_cfr_option_form) +
|
|
||||||
sizeof(struct lb_cfr_varbinary) +
|
|
||||||
strlen(name) + 1 + 3 +
|
|
||||||
sizeof(struct lb_cfr_numeric_option) +
|
|
||||||
sizeof(struct lb_cfr_varbinary) +
|
|
||||||
strlen(optname) + 1 + 2 +
|
|
||||||
sizeof(struct lb_cfr_varbinary) +
|
|
||||||
strlen(uiname) + 1 = 120
|
|
||||||
uint64_t object_id; = 1
|
|
||||||
uint64_t dependency_id; = 0
|
|
||||||
uint32_t flags; = 0
|
|
||||||
}
|
|
||||||
struct lb_cfr_varbinary {
|
|
||||||
uint32_t tag; = CFR_TAG_VARCHAR_UI_NAME
|
|
||||||
uint32_t size; = sizeof(struct lb_cfr_varbinary) +
|
|
||||||
strlen(name) + 1 + 3 = 20
|
|
||||||
uint32_t data_length; = strlen(name) + 1
|
|
||||||
};
|
|
||||||
char name[5]; = "test"
|
|
||||||
char padding[3];
|
|
||||||
struct lb_cfr_numeric_option {
|
|
||||||
uint32_t tag; = CFR_TAG_OPTION_BOOL
|
|
||||||
uint32_t size; = sizeof(struct lb_cfr_numeric_option) +
|
|
||||||
sizeof(struct lb_cfr_varbinary) +
|
|
||||||
strlen(optname) + 1 + 2 +
|
|
||||||
sizeof(struct lb_cfr_varbinary) +
|
|
||||||
strlen(uiname) + 1 = 72
|
|
||||||
uint64_t object_id; = 2
|
|
||||||
uint64_t dependency_id; = 0
|
|
||||||
uint32_t flags; = 0
|
|
||||||
uint32_t default_value; = true
|
|
||||||
};
|
|
||||||
struct lb_cfr_varbinary {
|
|
||||||
uint32_t tag; = CFR_TAG_VARCHAR_OPT_NAME
|
|
||||||
uint32_t size; = sizeof(struct lb_cfr_varbinary) +
|
|
||||||
strlen(optname) + 1 + 2 = 20
|
|
||||||
uint32_t data_length; = strlen(optname) + 1 = 6
|
|
||||||
};
|
|
||||||
char optname[6]; = "First"
|
|
||||||
char padding[2];
|
|
||||||
struct lb_cfr_varbinary {
|
|
||||||
uint32_t tag; = CFR_TAG_VARCHAR_UI_NAME
|
|
||||||
uint32_t size; = sizeof(struct lb_cfr_varbinary) +
|
|
||||||
strlen(uiname) + 1 = 20
|
|
||||||
uint32_t data_length; = strlen(uiname) + 1 = 8
|
|
||||||
};
|
|
||||||
char uiname[8]; = "Boolean"
|
|
||||||
```
|
|
||||||
|
|
@ -1,190 +0,0 @@
|
||||||
# CFR - coreboot form representation - Internals
|
|
||||||
|
|
||||||
This documents the API internally used by coreboot to be used
|
|
||||||
by ramstage code.
|
|
||||||
|
|
||||||
Please read [CFR](cfr.md) first.
|
|
||||||
|
|
||||||
## Enabling CFR support
|
|
||||||
|
|
||||||
Users should select `DRIVERS_OPTION_CFR` in Kconfig to enable CFR
|
|
||||||
support. Mainboards should select `DRIVERS_OPTION_CFR_ENABLED` to
|
|
||||||
enable `DRIVERS_OPTION_CFR` by default.
|
|
||||||
|
|
||||||
## Using CFR
|
|
||||||
|
|
||||||
When CFR support is enabled there are two possibilites to generate
|
|
||||||
the records:
|
|
||||||
|
|
||||||
- mainboard specific code
|
|
||||||
- automatic collection
|
|
||||||
|
|
||||||
In both cases you have to add `C` structs in ramstage to describe the
|
|
||||||
option and group them together into a form. CFR objects should reside
|
|
||||||
on the heap as they can be modified to match the current boot flow.
|
|
||||||
|
|
||||||
### Overriding default values
|
|
||||||
|
|
||||||
Mainboards often want to reuse CFR objects defined in SoC or common code
|
|
||||||
but with different default values. Rather than duplicating the entire object
|
|
||||||
definition, mainboards can declare an override table that maps option names
|
|
||||||
to new default values.
|
|
||||||
|
|
||||||
**Example:** Override defaults for several SoC-defined options:
|
|
||||||
|
|
||||||
```
|
|
||||||
#include <drivers/option/cfr_frontend.h>
|
|
||||||
#include <intelblocks/pcie_rp.h>
|
|
||||||
|
|
||||||
const struct cfr_default_override mb_cfr_overrides[] = {
|
|
||||||
CFR_OVERRIDE_BOOL("s0ix_enable", false),
|
|
||||||
CFR_OVERRIDE_ENUM("pciexp_aspm", ASPM_DISABLE),
|
|
||||||
CFR_OVERRIDE_NUMBER("igd_dvmt", 64),
|
|
||||||
CFR_OVERRIDE_END
|
|
||||||
};
|
|
||||||
|
|
||||||
void mb_cfr_setup_menu(struct lb_cfr *cfr_root)
|
|
||||||
{
|
|
||||||
/* Register overrides before writing menu */
|
|
||||||
cfr_register_overrides(mb_cfr_overrides);
|
|
||||||
cfr_write_setup_menu(cfr_root, sm_root);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
When the CFR system writes the setup menu, it will check the override table
|
|
||||||
for each option and use the override value if one exists. All other object
|
|
||||||
metadata (name, help text, enum values, flags) comes from the original object.
|
|
||||||
|
|
||||||
The following helper macros are available to populate the table:
|
|
||||||
|
|
||||||
- `CFR_OVERRIDE_BOOL(name, value)`
|
|
||||||
- `CFR_OVERRIDE_ENUM(name, value)`
|
|
||||||
- `CFR_OVERRIDE_NUMBER(name, value)`
|
|
||||||
- `CFR_OVERRIDE_VARCHAR(name, value)`
|
|
||||||
- `CFR_OVERRIDE_END`
|
|
||||||
|
|
||||||
Each macro encodes the override type, and the CFR backend validates that the
|
|
||||||
override type matches the original object's type. If the types do not match,
|
|
||||||
the override is ignored and a warning is printed.
|
|
||||||
|
|
||||||
### Updating CFR options
|
|
||||||
|
|
||||||
The CFR options should be updated before tables are written.
|
|
||||||
You can use a callback, using the `WITH_CALLBACK()` macro, to update
|
|
||||||
single or multiple options when the CFR table is written into the
|
|
||||||
coreboot table.
|
|
||||||
|
|
||||||
**Example:** Updates the option serial_number with the contents from the
|
|
||||||
EMI eeprom.
|
|
||||||
|
|
||||||
```
|
|
||||||
static void update_serial(struct sm_object *new)
|
|
||||||
{
|
|
||||||
new->sm_varchar.default_value = get_emi_eeprom_vpd()->serial_number;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct sm_object serial_number = SM_DECLARE_VARCHAR({
|
|
||||||
.flags = CFR_OPTFLAG_READONLY | CFR_OPTFLAG_VOLATILE,
|
|
||||||
.opt_name = "serial_number",
|
|
||||||
.ui_name = "Serial Number",
|
|
||||||
}, WITH_CALLBACK(update_serial));
|
|
||||||
```
|
|
||||||
|
|
||||||
### Dependencies in CFR options
|
|
||||||
|
|
||||||
The CFR options can have a dependency that must be evaluated at runtime by
|
|
||||||
the OS/payload that parses the CFR record and displays the UI.
|
|
||||||
By using the `WITH_DEP()` macro you can specify another numeric option that
|
|
||||||
is checked to hide the current option. The `WITH_DEP_VALUES()` macro allows
|
|
||||||
specifying one or more values that cause the dependent option to be displayed.
|
|
||||||
|
|
||||||
**Example:** Declares a dependency from `sata_disable_port0` to `sata_enable`.
|
|
||||||
The option `sata_disable_port0` will be hidden as long as "sata_enable" is 0.
|
|
||||||
When the user changes "sata_enable" to 1 or it was 1 then the option
|
|
||||||
`sata_disable_port0` should be visible.
|
|
||||||
|
|
||||||
```
|
|
||||||
static struct sm_object sata_enable = SM_DECLARE_BOOL({
|
|
||||||
.flags = CFR_OPTFLAG_RUNTIME,
|
|
||||||
.opt_name = "sata_enable",
|
|
||||||
.ui_name = "Enable SATA controller",
|
|
||||||
.ui_helptext = NULL,
|
|
||||||
.default_value = true,
|
|
||||||
});
|
|
||||||
|
|
||||||
static struct sm_object sata_disable_port0 = SM_DECLARE_BOOL({
|
|
||||||
.flags = CFR_OPTFLAG_RUNTIME,
|
|
||||||
.opt_name = "sata_disable_port0",
|
|
||||||
.ui_name = "Disable SATA port #0",
|
|
||||||
.ui_helptext = NULL,
|
|
||||||
.default_value = false,
|
|
||||||
}, WITH_DEP(&sata_enable));
|
|
||||||
```
|
|
||||||
|
|
||||||
**Example:** Declares a dependency from `com1_termination` to `com1_mode`.
|
|
||||||
The option `com1_termination` will only be shown if `com1_mode` is set to RS-485.
|
|
||||||
|
|
||||||
```
|
|
||||||
#define COM_MODE_DISABLED 3
|
|
||||||
#define COM_MODE_RS232 0
|
|
||||||
#define COM_MODE_RS485 1
|
|
||||||
|
|
||||||
static struct sm_object com1_mode = SM_DECLARE_ENUM({
|
|
||||||
.flags = CFR_OPTFLAG_RUNTIME,
|
|
||||||
.opt_name = "com1_mode",
|
|
||||||
.ui_name = "COM1 Mode",
|
|
||||||
.ui_helptext = NULL,
|
|
||||||
.default_value = 1,
|
|
||||||
.values = (const struct sm_enum_value[]) {
|
|
||||||
{ "Disabled", COM_MODE_DISABLED },
|
|
||||||
{ "RS-232", COM_MODE_RS232 },
|
|
||||||
{ "RS-485", COM_MODE_RS485 },
|
|
||||||
SM_ENUM_VALUE_END },
|
|
||||||
});
|
|
||||||
|
|
||||||
static struct sm_object com1_termination = SM_DECLARE_BOOL({
|
|
||||||
.flags = CFR_OPTFLAG_RUNTIME,
|
|
||||||
.opt_name = "com1_termination",
|
|
||||||
.ui_name = "Enable COM1 termination resistors",
|
|
||||||
.ui_helptext = NULL,
|
|
||||||
.default_value = false,
|
|
||||||
}, WITH_DEP_VALUES(&com1_mode, COM_MODE_RS485));
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
### Providing mainboard custom options
|
|
||||||
|
|
||||||
A mainboard that uses CFR can provide a list of custom options
|
|
||||||
be overwriting the weak `void mb_cfr_setup_menu(struct lb_cfr *cfr_root);`
|
|
||||||
function in ramstage.
|
|
||||||
|
|
||||||
### Automatic CFR collection
|
|
||||||
|
|
||||||
CFR forms that have the `__cfr_form` attribute are automatically collected
|
|
||||||
and inserted into the coreboot table.
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
The following CFR form `southbridge` will be automatically added to the
|
|
||||||
coreboot table and it will have a single option called `Enable NMI` that
|
|
||||||
allows the variable `nmi` to be changed to *0* or *1*.
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
```C
|
|
||||||
static struct sm_object nmi = SM_DECLARE_BOOL({
|
|
||||||
.flags = CFR_OPTFLAG_RUNTIME,
|
|
||||||
.opt_name = "nmi",
|
|
||||||
.ui_name = "Enable NMI",
|
|
||||||
.ui_helptext = NULL,
|
|
||||||
.default_value = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
static const __cfr_form struct sm_obj_form southbridge = {
|
|
||||||
.flags = 0,
|
|
||||||
.ui_name = "Southbridge",
|
|
||||||
.obj_list = (const struct sm_object *[]) {
|
|
||||||
&nmi,
|
|
||||||
NULL
|
|
||||||
},
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
# Generating signed UEFI capsules with EDK2
|
|
||||||
|
|
||||||
coreboot can cooperate with an EDK2 payload to support firmware updates via the UEFI
|
|
||||||
ESRT/FMP capsule mechanism.
|
|
||||||
|
|
||||||
This document covers generating a *signed* capsule during the coreboot build.
|
|
||||||
|
|
||||||
At present, capsule generation requires a compatible EDK2 tree with the
|
|
||||||
corresponding payload-side changes. Upstream support is being tracked in:
|
|
||||||
|
|
||||||
https://github.com/tianocore/edk2/pull/12053
|
|
||||||
|
|
||||||
Older EDK2 trees may be missing pieces required by this integration.
|
|
||||||
|
|
||||||
## Build-time capsule generation
|
|
||||||
|
|
||||||
Enable capsule support and use an EDK2 payload:
|
|
||||||
|
|
||||||
- `CONFIG_DRIVERS_EFI_UPDATE_CAPSULES`: enable coreboot capsule update support.
|
|
||||||
- `CONFIG_DRIVERS_EFI_GENERATE_CAPSULE`: generate `build/coreboot.cap` after the ROM is finalised.
|
|
||||||
- `CONFIG_PAYLOAD_EDK2`: build an EDK2 payload.
|
|
||||||
|
|
||||||
When enabled, the coreboot build generates `build/coreboot.cap` after the ROM image is
|
|
||||||
finalised. The capsule can also be generated explicitly with `make capsule`.
|
|
||||||
|
|
||||||
Configure the FMAP allowlist embedded into the ROM as a manifest:
|
|
||||||
|
|
||||||
- `CONFIG_DRIVERS_EFI_CAPSULE_REGIONS`: whitespace-separated FMAP region allowlist embedded into
|
|
||||||
the ROM as a manifest (e.g. `COREBOOT EC`).
|
|
||||||
|
|
||||||
Configure the ESRT/FMP firmware identity used by the capsule:
|
|
||||||
|
|
||||||
- `CONFIG_DRIVERS_EFI_MAIN_FW_GUID`: GUID of the firmware
|
|
||||||
- `CONFIG_DRIVERS_EFI_MAIN_FW_VERSION`: firmware version encoded in the capsule header;
|
|
||||||
if set to `0`, derive a value from the leading `<major>.<minor>` in
|
|
||||||
`CONFIG_LOCALVERSION` when possible
|
|
||||||
- `CONFIG_DRIVERS_EFI_MAIN_FW_LSV`: lowest supported firmware version; if set to `0`,
|
|
||||||
use the resolved firmware version
|
|
||||||
|
|
||||||
Reset behavior during capsule application:
|
|
||||||
|
|
||||||
- `CONFIG_DRIVERS_EFI_CAPSULE_INITIATE_RESET`: add the capsule `InitiateReset` flag.
|
|
||||||
This is disabled by default because Linux rejects capsules with `InitiateReset` when using
|
|
||||||
`/dev/efi_capsule_loader`.
|
|
||||||
|
|
||||||
## Embedded drivers (FmpDxe in capsule)
|
|
||||||
|
|
||||||
Some EDK2 capsule update flows use an embedded `FmpDxe.efi` driver inside the capsule.
|
|
||||||
|
|
||||||
To generate capsules with an embedded `FmpDxe.efi`, enable:
|
|
||||||
|
|
||||||
- `CONFIG_DRIVERS_EFI_CAPSULE_EMBED_FMP_DXE`: embed `FmpDxe.efi` into generated capsules.
|
|
||||||
- `CONFIG_DRIVERS_EFI_CAPSULE_ACCEPT_EMBEDDED_DRIVERS`: configure the EDK2 payload to accept
|
|
||||||
capsules with embedded drivers (sets `PcdCapsuleEmbeddedDriverSupport=TRUE`).
|
|
||||||
|
|
||||||
Note: if Secure Boot is enabled, the embedded driver must be signed by a key trusted by the
|
|
||||||
running firmware, otherwise capsule processing may fail when loading the embedded driver.
|
|
||||||
|
|
||||||
## Capsule signing certificates
|
|
||||||
|
|
||||||
`GenerateCapsule` can sign the FMP payload (PKCS#7). Many platforms require signed capsules.
|
|
||||||
|
|
||||||
coreboot exposes three Kconfig options for the certificate chain:
|
|
||||||
|
|
||||||
- `CONFIG_DRIVERS_EFI_CAPSULE_SIGNER_PRIVATE_CERT`: PEM containing the signing private key and
|
|
||||||
leaf certificate
|
|
||||||
- `CONFIG_DRIVERS_EFI_CAPSULE_OTHER_PUBLIC_CERT`: PEM intermediate certificate
|
|
||||||
- `CONFIG_DRIVERS_EFI_CAPSULE_TRUSTED_PUBLIC_CERT`: PEM trusted root certificate
|
|
||||||
|
|
||||||
If a configured path is relative, it is interpreted relative to the configured EDK2 repository
|
|
||||||
inside `payloads/external/edk2/workspace`.
|
|
||||||
|
|
||||||
The defaults use the EDK2 BaseTools test certificate chain. Do not use the test keys for
|
|
||||||
production firmware updates.
|
|
||||||
|
|
||||||
To generate your own certificate chain and convert it into the required PEM files, see:
|
|
||||||
`BaseTools/Source/Python/Pkcs7Sign/Readme.md` in the EDK2 tree.
|
|
||||||
|
|
@ -6,28 +6,12 @@ they allow to easily reuse existing code across platforms.
|
||||||
|
|
||||||
For details on how to connect device drivers to a mainboard, see [Driver Devicetree Entries](dt_entries.md).
|
For details on how to connect device drivers to a mainboard, see [Driver Devicetree Entries](dt_entries.md).
|
||||||
|
|
||||||
```{toctree}
|
|
||||||
:maxdepth: 1
|
|
||||||
:hidden:
|
|
||||||
|
|
||||||
Driver Devicetree Entries <dt_entries.md>
|
|
||||||
```
|
|
||||||
|
|
||||||
Some of the drivers currently available include:
|
Some of the drivers currently available include:
|
||||||
|
|
||||||
```{toctree}
|
* [Intel DPTF](dptf.md)
|
||||||
:maxdepth: 1
|
* [IPMI KCS](ipmi_kcs.md)
|
||||||
|
* [SMMSTORE](smmstore.md)
|
||||||
ACPI Five-Level Fan Control <acpi_fan_control.md>
|
* [SMMSTOREv2](smmstorev2.md)
|
||||||
CFR <cfr.md>
|
* [SoundWire](soundwire.md)
|
||||||
CFR use within coreboot <cfr_internal.md>
|
* [USB4 Retimer](retimer.md)
|
||||||
Intel DPTF <dptf.md>
|
* [CBFS SMBIOS hooks](cbfs_smbios.md)
|
||||||
IPMI BT (Block Transfer) <ipmi_bt.md>
|
|
||||||
IPMI KCS <ipmi_kcs.md>
|
|
||||||
SMMSTORE <smmstore.md>
|
|
||||||
SMMSTOREv2 <smmstorev2.md>
|
|
||||||
SoundWire <soundwire.md>
|
|
||||||
USB4 Retimer <retimer.md>
|
|
||||||
CBFS SMBIOS hooks <cbfs_smbios.md>
|
|
||||||
EDK2 capsule generation <efi_capsule_generation.md>
|
|
||||||
```
|
|
||||||
|
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
# IPMI Block Transfer (BT) driver
|
|
||||||
|
|
||||||
The driver can be found in `src/drivers/ipmi/` (same as KCS). It works with BMC
|
|
||||||
that provides a BT I/O interface as specified in the [IPMI] standard. See
|
|
||||||
"Intelligent Platform Management Interface Specification", v2.0, Rev. 1.1 for
|
|
||||||
more details on the interface and IPMI in general.
|
|
||||||
|
|
||||||
The driver detects the IPMI version and reserves the I/O space in coreboot's
|
|
||||||
resource allocator.
|
|
||||||
|
|
||||||
## For developers
|
|
||||||
|
|
||||||
To use the driver, select the `IPMI_BT` Kconfig and add the following PNP
|
|
||||||
device (in example for the BT at 0xe4):
|
|
||||||
|
|
||||||
```
|
|
||||||
chip drivers/ipmi
|
|
||||||
device pnp e4.0 on end # IPMI BT
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note:** The I/O base address must be aligned to 4.
|
|
||||||
|
|
||||||
The following settings can be set in a device tree:
|
|
||||||
|
|
||||||
```{eval-rst}
|
|
||||||
+------------------+--------------+-------------------------------------------+
|
|
||||||
| Setting | Type/Default | Description/Purpose |
|
|
||||||
+==================+==============+===========================================+
|
|
||||||
| wait_for_bmc | | Boolean | Wait for BMC to boot. This can be used if |
|
|
||||||
| | | false | the BMC takes a long time to boot after |
|
|
||||||
| | | PoR. |
|
|
||||||
+------------------+--------------+-------------------------------------------+
|
|
||||||
| bmc_boot_timeout | | Integer | The timeout in seconds to wait for the |
|
|
||||||
| | | 0 | IPMI service to be loaded. Will be used |
|
|
||||||
| | | if wait_for_bmc is true. |
|
|
||||||
+------------------+--------------+-------------------------------------------+
|
|
||||||
```
|
|
||||||
|
|
||||||
## Debugging/testing the driver
|
|
||||||
|
|
||||||
`ipmi_sim` from [OpenIPMI] project can be used by running `ipmi_sim -d` in one
|
|
||||||
console to watch what's being sent/received and starting QEMU like this in
|
|
||||||
another console:
|
|
||||||
|
|
||||||
```
|
|
||||||
qemu-system-x86_64 \
|
|
||||||
-M q35,smm=on \
|
|
||||||
-bios build/coreboot.rom \
|
|
||||||
-chardev socket,id=ipmichr0,host=localhost,port=9002,reconnect=10 \
|
|
||||||
-device ipmi-bmc-extern,chardev=ipmichr0,id=bmc0 \
|
|
||||||
-device isa-ipmi-bt,bmc=bmc0,irq=0 \
|
|
||||||
-serial stdio
|
|
||||||
```
|
|
||||||
|
|
||||||
A simpler alternative is to use QEMU's builtin BMC simulator:
|
|
||||||
|
|
||||||
```
|
|
||||||
qemu-system-x86_64 \
|
|
||||||
-M q35,smm=on \
|
|
||||||
-bios build/coreboot.rom \
|
|
||||||
-device ipmi-bmc-sim,id=bmc0 \
|
|
||||||
-device isa-ipmi-bt,bmc=bmc0,irq=0 \
|
|
||||||
-serial stdio
|
|
||||||
```
|
|
||||||
|
|
||||||
## References
|
|
||||||
|
|
||||||
Useful links on the subject:
|
|
||||||
* README of `ipmi_sim`:
|
|
||||||
<https://github.com/wrouesnel/openipmi/blob/master/lanserv/README.ipmi_sim>
|
|
||||||
* slides about OpenIPMI:
|
|
||||||
<https://www.linux-kvm.org/images/7/76/03x08-Juniper-Corey_Minyard-UsingIPMIinQEMU.ods.pdf>
|
|
||||||
* a usage example: <https://github.com/dhilst/qemu-ipmi>
|
|
||||||
* old docs (the options are still there, but no longer have a dedicated page in
|
|
||||||
modern documentation): <https://hskinnemoen.github.io/qemu/specs/ipmi.html>
|
|
||||||
|
|
||||||
[IPMI]: https://www.intel.com/content/dam/www/public/us/en/documents/specification-updates/ipmi-intelligent-platform-mgt-interface-spec-2nd-gen-v2-0-spec-update.pdf
|
|
||||||
[OpenIPMI]: https://github.com/wrouesnel/openipmi
|
|
||||||
|
|
@ -128,8 +128,7 @@ data or modify the currently running kernel.*
|
||||||
|
|
||||||
## External links
|
## External links
|
||||||
|
|
||||||
* [A Tour Beyond BIOS Implementing UEFI Authenticated Variables in SMM with EDK II](https://github.com/tianocore-docs/Docs/raw/master/White_Papers/A_Tour_Beyond_BIOS_Implementing_UEFI_Authenticated_Variables_in_SMM_with_EDKII_V2.pdf)
|
* [A Tour Beyond BIOS Implementing UEFI Authenticated Variables in SMM with EDKI](https://software.intel.com/sites/default/files/managed/cf/ea/a_tour_beyond_bios_implementing_uefi_authenticated_variables_in_smm_with_edkii.pdf)
|
||||||
|
|
||||||
Note, this differs significantly from coreboot's implementation.
|
Note, this differs significantly from coreboot's implementation.
|
||||||
|
|
||||||
[SMM]: ../security/smm.md
|
[SMM]: ../security/smm.md
|
||||||
|
|
|
||||||
|
|
@ -74,30 +74,19 @@ has to read the coreboot table with tag `0x0039`, containing:
|
||||||
struct lb_smmstorev2 {
|
struct lb_smmstorev2 {
|
||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint32_t num_blocks; /* Number of writable blocks in SMM */
|
uint32_t num_blocks; /* Number of writeable blocks in SMM */
|
||||||
uint32_t block_size; /* Size of a block in byte. Default: 64 KiB */
|
uint32_t block_size; /* Size of a block in byte. Default: 64 KiB */
|
||||||
uint32_t mmap_addr_deprecated; /* 32-bit MMIO address of the store for read only access.
|
uint32_t mmap_addr; /* MMIO address of the store for read only access */
|
||||||
Prefer 'mmap_addr' for new software.
|
uint32_t com_buffer; /* Physical address of the communication buffer */
|
||||||
Zero when the address won't fit into 32-bits. */
|
uint32_t com_buffer_size; /* Size of the communication buffer in byte */
|
||||||
uint32_t com_buffer; /* Physical address of the communication buffer */
|
uint8_t apm_cmd; /* The command byte to write to the APM I/O port */
|
||||||
uint32_t com_buffer_size; /* Size of the communication buffer in bytes */
|
uint8_t unused[3]; /* Set to zero */
|
||||||
uint8_t apm_cmd; /* The command byte to write to the APM I/O port */
|
|
||||||
uint8_t unused[3]; /* Set to zero */
|
|
||||||
uint64_t mmap_addr; /* 64-bit MMIO address of the store for read only access.
|
|
||||||
Introduced after the initial implementation. Users of
|
|
||||||
this table must check the 'size' field to detect if its
|
|
||||||
written out by coreboot. */
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
The absence of this coreboot table entry indicates that there's no
|
The absence of this coreboot table entry indicates that there's no
|
||||||
SMMSTOREv2 support.
|
SMMSTOREv2 support.
|
||||||
|
|
||||||
`mmap_addr` is an optional field added after the initial implementation.
|
|
||||||
Users of this table must check the size field to know if it's written by coreboot.
|
|
||||||
In case it's not present 'mmap_addr_deprecated' is to be used as the SPI ROM MMIO
|
|
||||||
address and it must be below 4 GiB.
|
|
||||||
|
|
||||||
### Blocks
|
### Blocks
|
||||||
|
|
||||||
The SMMSTOREv2 splits the SMMSTORE FMAP partition into smaller chunks
|
The SMMSTOREv2 splits the SMMSTORE FMAP partition into smaller chunks
|
||||||
|
|
@ -135,9 +124,25 @@ additional calling arguments are passed via `%ebx`.
|
||||||
**NOTE**: The size of the struct entries are in the native word size of
|
**NOTE**: The size of the struct entries are in the native word size of
|
||||||
smihandler. This means 32 bits in almost all cases.
|
smihandler. This means 32 bits in almost all cases.
|
||||||
|
|
||||||
#### - SMMSTORE_CMD_INIT_DEPRECATED = 4
|
#### - SMMSTORE_CMD_INIT = 4
|
||||||
|
|
||||||
Unused, returns SMMSTORE_REG_UNSUPPORTED.
|
This installs the communication buffer to use and thus enables the
|
||||||
|
SMMSTORE handler. This command can only be executed once and is done
|
||||||
|
by the firmware. Calling this function at runtime has no effect.
|
||||||
|
|
||||||
|
The additional parameter buffer `%ebx` contains a pointer to the
|
||||||
|
following struct:
|
||||||
|
|
||||||
|
```C
|
||||||
|
struct smmstore_params_init {
|
||||||
|
uint32_t com_buffer;
|
||||||
|
uint32_t com_buffer_size;
|
||||||
|
} __packed;
|
||||||
|
```
|
||||||
|
|
||||||
|
INPUT:
|
||||||
|
- `com_buffer`: Physical address of the communication buffer (CBMEM)
|
||||||
|
- `com_buffer_size`: Size in bytes of the communication buffer
|
||||||
|
|
||||||
#### - SMMSTORE_CMD_RAW_READ = 5
|
#### - SMMSTORE_CMD_RAW_READ = 5
|
||||||
|
|
||||||
|
|
@ -208,49 +213,9 @@ coreboot tables, there's no risk that a malicious application capable
|
||||||
of issuing SMIs could extract arbitrary data or modify the currently
|
of issuing SMIs could extract arbitrary data or modify the currently
|
||||||
running kernel.
|
running kernel.
|
||||||
|
|
||||||
## Capsule update API
|
|
||||||
|
|
||||||
Availability of this command is tied to `CONFIG_DRIVERS_EFI_UPDATE_CAPSULES`.
|
|
||||||
|
|
||||||
To allow updating full flash content (except if locked at hardware
|
|
||||||
level), few new calls were added. They reuse communication buffer, SMI
|
|
||||||
command, return values and calling arguments of SMMSTORE commands listed
|
|
||||||
above, with the exception of subcommand passed via `%ah`. If the
|
|
||||||
subcommand is to operate on full flash size, it has the highest bit set,
|
|
||||||
e.g. it is `0x85` for `SMMSTORE_CMD_RAW_READ` and `0x86` for
|
|
||||||
`SMMSTORE_CMD_RAW_WRITE`. Every `block_id` describes block relative to
|
|
||||||
the beginning of a flash, maximum value depends on its size.
|
|
||||||
|
|
||||||
Attempts to write the protected memory regions can lead to undesired
|
|
||||||
consequences ranging from system instability to bricking and security
|
|
||||||
vulnerabilities. When this feature is used, care must be taken to temporarily
|
|
||||||
lift protections for the duration of an update when the whole flash is
|
|
||||||
rewritten or the update must be constrained to affect only writable portions of
|
|
||||||
the flash (e.g., "BIOS" region).
|
|
||||||
|
|
||||||
There is one new subcommand that must be called before any other subcommands
|
|
||||||
with highest bit set can be used.
|
|
||||||
|
|
||||||
### - SMMSTORE_CMD_USE_FULL_FLASH = 0x80
|
|
||||||
|
|
||||||
This command can only be executed once and is done by the firmware.
|
|
||||||
Calling this function at runtime has no effect. It takes one additional
|
|
||||||
parameter that, contrary to other commands, isn't a pointer. Instead,
|
|
||||||
`%ebx` indicates requested state of full flash access. If it equals 0,
|
|
||||||
commands for accessing full flash are permanently disabled, otherwise
|
|
||||||
they are permanently enabled until the next boot.
|
|
||||||
|
|
||||||
The assumption is that if capsule updates are enabled at build time and
|
|
||||||
whole flash access is enabled at runtime, a UEFI payload (highly likely
|
|
||||||
EDK2 or its derivative) won't allow a regular OS to boot if the handler is
|
|
||||||
enabled without rebooting first. There could be a way of deactivating the
|
|
||||||
handler, but coreboot, having no way of enforcing its usage, might as well
|
|
||||||
permit access until a reboot and rely on the payload to do the right thing.
|
|
||||||
|
|
||||||
## External links
|
## External links
|
||||||
|
|
||||||
* [A Tour Beyond BIOS Implementing UEFI Authenticated Variables in SMM with EDK II](https://github.com/tianocore-docs/Docs/raw/master/White_Papers/A_Tour_Beyond_BIOS_Implementing_UEFI_Authenticated_Variables_in_SMM_with_EDKII_V2.pdf)
|
* [A Tour Beyond BIOS Implementing UEFI Authenticated Variables in SMM with EDKI](https://software.intel.com/sites/default/files/managed/cf/ea/a_tour_beyond_bios_implementing_uefi_authenticated_variables_in_smm_with_edkii.pdf)
|
||||||
|
|
||||||
Note that this differs significantly from coreboot's implementation.
|
Note that this differs significantly from coreboot's implementation.
|
||||||
|
|
||||||
[SMM]: ../security/smm.md
|
[SMM]: ../security/smm.md
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ The bootblock loads the romstage or the verstage if verified boot is enabled.
|
||||||
|
|
||||||
### Cache-As-Ram
|
### Cache-As-Ram
|
||||||
The *Cache-As-Ram*, also called Non-Eviction mode, or *CAR* allows to use the
|
The *Cache-As-Ram*, also called Non-Eviction mode, or *CAR* allows to use the
|
||||||
CPU cache like regular SRAM. This is particularly useful for high level
|
CPU cache like regular SRAM. This is particullary useful for high level
|
||||||
languages like `C`, which need RAM for heap and stack.
|
languages like `C`, which need RAM for heap and stack.
|
||||||
|
|
||||||
The CAR needs to be activated using vendor specific CPU instructions.
|
The CAR needs to be activated using vendor specific CPU instructions.
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,9 @@ $(call add_intermediate, add_mrc_data)
|
||||||
|
|
||||||
Note that the second line must start with a tab, not spaces.
|
Note that the second line must start with a tab, not spaces.
|
||||||
|
|
||||||
See also <project:../tutorial/managing_local_additions.md>.
|
```eval_rst
|
||||||
|
See also :doc:`../tutorial/managing_local_additions`.
|
||||||
|
```
|
||||||
|
|
||||||
#### FMAP region support
|
#### FMAP region support
|
||||||
With the addition of FMAP flash partitioning support to coreboot, there was a
|
With the addition of FMAP flash partitioning support to coreboot, there was a
|
||||||
|
|
|
||||||
|
|
@ -1,361 +0,0 @@
|
||||||
# CBMEM high table memory manager
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
|
|
||||||
CBMEM (coreboot memory) is a dynamic memory infrastructure used in
|
|
||||||
coreboot to store runtime data structures, logs, and other information
|
|
||||||
that needs to persist across different boot stages, and even across warm
|
|
||||||
boots. CBMEM is crucial for maintaining state and information through
|
|
||||||
the coreboot boot process.
|
|
||||||
|
|
||||||
Its key responsibilities include:
|
|
||||||
- Providing a stable storage area for critical boot data
|
|
||||||
- Managing console logging
|
|
||||||
- Storing configuration tables for hand off to payloads
|
|
||||||
- Maintaining timestamps for performance analysis
|
|
||||||
- Preserving boot state during S3 suspend/resume cycles
|
|
||||||
- Storing data such as ACPI tables, SMBIOS tables and coreboot tables
|
|
||||||
which are used at runtime
|
|
||||||
|
|
||||||
|
|
||||||
## Creation and Placement
|
|
||||||
|
|
||||||
CBMEM is initialized by coreboot during romstage, but is used mainly in
|
|
||||||
ramstage for storing any data that needs to be saved for more than a
|
|
||||||
short period of time.
|
|
||||||
|
|
||||||
For 32-bit builds, CBMEM is typically located at the highest usable DRAM
|
|
||||||
address below the 4GiB boundary. For 64-bit builds, while there is no
|
|
||||||
strict upper limit, it is advisable to follow the same guidelines to
|
|
||||||
prevent access or addressing issues. Regardless of the build type, the
|
|
||||||
CBMEM address must remain consistent between romstage and ramstage.
|
|
||||||
|
|
||||||
Each platform may need to implement its own method for determining the
|
|
||||||
`cbmem_top` address, as this can depend on specific hardware
|
|
||||||
configurations and memory layouts.
|
|
||||||
|
|
||||||
|
|
||||||
## Architecture Overview
|
|
||||||
|
|
||||||
Each CBMEM region is identified by a unique ID, allowing different
|
|
||||||
components to store and retrieve their data during runtime.
|
|
||||||
|
|
||||||
Upon creating an entry, a block of memory of the requested size is
|
|
||||||
allocated from the reserved CBMEM region. This region typically persists
|
|
||||||
across warm reboots, making it useful for debugging and passing
|
|
||||||
information to payloads.
|
|
||||||
|
|
||||||
CBMEM is implemented as a specialized in-memory database (IMD) system
|
|
||||||
that grows downward from a defined upper memory limit. This means that
|
|
||||||
only the latest added entry may be removed.
|
|
||||||
|
|
||||||
```text
|
|
||||||
High Memory
|
|
||||||
+----------------------+ <- cbmem_top
|
|
||||||
| Root Pointer |
|
|
||||||
|----------------------|
|
|
||||||
| Root Structure |
|
|
||||||
|----------------------|
|
|
||||||
| Entry 1 |
|
|
||||||
|----------------------|
|
|
||||||
| Entry 2 |
|
|
||||||
|----------------------|
|
|
||||||
| ... |
|
|
||||||
| (grows downward) |
|
|
||||||
+----------------------+
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Core Components
|
|
||||||
|
|
||||||
The CBMEM system consists of several key components:
|
|
||||||
|
|
||||||
1. **Root Pointer**: Located at the very top of CBMEM memory space,
|
|
||||||
contains a magic number and offset to the Root Structure
|
|
||||||
|
|
||||||
2. **Root Structure**: Contains metadata about the CBMEM region,
|
|
||||||
including:
|
|
||||||
- Entry alignment requirements
|
|
||||||
- Maximum number of entries
|
|
||||||
- Current number of entries
|
|
||||||
- Address of the lowest allocated memory
|
|
||||||
|
|
||||||
3. **Entries**: Individual allocations within CBMEM, identified by:
|
|
||||||
- 32-bit ID (often encoding ASCII characters for readability)
|
|
||||||
- Size information
|
|
||||||
- Magic validation value
|
|
||||||
|
|
||||||
4. **IMD Implementation**: The underlying memory management system
|
|
||||||
that handles allocation, deallocation, and entry management
|
|
||||||
|
|
||||||
|
|
||||||
## Memory Layout and Initialization
|
|
||||||
|
|
||||||
CBMEM is positioned at the top of available system RAM, typically
|
|
||||||
just below the 4GiB boundary for 32-bit builds. This placement
|
|
||||||
ensures compatibility with legacy code while allowing CBMEM to
|
|
||||||
retain its contents across warm resets.
|
|
||||||
|
|
||||||
|
|
||||||
### CBMEM Location Determination
|
|
||||||
|
|
||||||
Each platform must implement a `cbmem_top_chipset()` function
|
|
||||||
that returns the physical address where CBMEM should be located.
|
|
||||||
This address must be consistent across coreboot stages and is
|
|
||||||
determined based on:
|
|
||||||
|
|
||||||
- Available physical memory
|
|
||||||
- Architecture-specific constraints
|
|
||||||
- BIOS/chipset requirements
|
|
||||||
|
|
||||||
|
|
||||||
### Initialization Process
|
|
||||||
|
|
||||||
CBMEM is initialized in a multi-step process:
|
|
||||||
|
|
||||||
1. **Early Initialization**: A small console buffer is created in during
|
|
||||||
bootblock and romstage
|
|
||||||
|
|
||||||
2. **RAM Initialization**: The full CBMEM area is established in
|
|
||||||
ramstage
|
|
||||||
|
|
||||||
3. **Normal Operation**:
|
|
||||||
- In a normal boot, CBMEM is created fresh
|
|
||||||
- Size and alignment values are specified
|
|
||||||
- Initial entries are allocated
|
|
||||||
|
|
||||||
4. **Recovery Operation**:
|
|
||||||
- During S3 resume, CBMEM structure is recovered from memory
|
|
||||||
- Content is validated using magic numbers and checksums
|
|
||||||
- All existing entries remain accessible
|
|
||||||
|
|
||||||
|
|
||||||
## Entry Management
|
|
||||||
|
|
||||||
CBMEM entries are identified by a 32-bit ID, often encoding ASCII
|
|
||||||
characters to indicate their purpose (for example, "CNSL" for console).
|
|
||||||
|
|
||||||
### Entry Creation
|
|
||||||
|
|
||||||
```c
|
|
||||||
void *cbmem_add(u32 id, u64 size);
|
|
||||||
```
|
|
||||||
|
|
||||||
This function:
|
|
||||||
- Searches for an existing entry with the given ID
|
|
||||||
- If found, returns the existing entry (size is ignored)
|
|
||||||
- If not found, allocates a new entry of the requested size
|
|
||||||
- Returns a pointer to the entry's data area
|
|
||||||
|
|
||||||
|
|
||||||
### Entry Access
|
|
||||||
|
|
||||||
```c
|
|
||||||
void *cbmem_find(u32 id);
|
|
||||||
```
|
|
||||||
|
|
||||||
This function:
|
|
||||||
- Searches for an entry with the specified ID
|
|
||||||
- Returns a pointer to the entry's data area if found
|
|
||||||
- Returns NULL if the entry does not exist
|
|
||||||
|
|
||||||
|
|
||||||
### Entry Removal
|
|
||||||
|
|
||||||
```c
|
|
||||||
int cbmem_entry_remove(const struct cbmem_entry *entry);
|
|
||||||
```
|
|
||||||
|
|
||||||
This function:
|
|
||||||
- Removes the specified entry if it was the last one added
|
|
||||||
- Returns 0 on success, negative value on failure
|
|
||||||
- Note: Due to the downward-growing design, only the most recently
|
|
||||||
added entry can be removed
|
|
||||||
|
|
||||||
|
|
||||||
## CBMEM Console Implementation
|
|
||||||
|
|
||||||
The CBMEM console is a circular buffer used for capturing log messages
|
|
||||||
across all boot stages. It is one of the most widely used CBMEM
|
|
||||||
features. The size of this buffer is determined by the
|
|
||||||
`CONFIG_CBMEM_CONSOLE_SIZE` Kconfig option.
|
|
||||||
|
|
||||||
|
|
||||||
### Console Structure
|
|
||||||
|
|
||||||
```c
|
|
||||||
struct cbmem_console {
|
|
||||||
u32 size; // Size of the buffer
|
|
||||||
u32 cursor; // Current write position and flags
|
|
||||||
u8 body[]; // Actual data buffer
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Key features:
|
|
||||||
- The high bit of `cursor` indicates overflow condition
|
|
||||||
- Only the lower 28 bits of `cursor` are used as position
|
|
||||||
- Supports ring-buffer operation when full
|
|
||||||
|
|
||||||
|
|
||||||
### Console Operation
|
|
||||||
|
|
||||||
1. **Initialization**: A console entry is created in CBMEM with ID
|
|
||||||
`CBMEM_ID_CONSOLE` (0x434f4e53 - 'CONS')
|
|
||||||
|
|
||||||
2. **Writing**: Log messages are written byte-by-byte using
|
|
||||||
`cbmemc_tx_byte()` which:
|
|
||||||
- Adds data to the current cursor position
|
|
||||||
- Advances the cursor
|
|
||||||
- Sets the overflow flag when wrapping around
|
|
||||||
|
|
||||||
3. **Stage Transition**: When transitioning between boot stages:
|
|
||||||
- Pre-RAM console contents are copied to the main CBMEM console
|
|
||||||
- Any overflow condition is preserved and noted
|
|
||||||
- The process ensures no log messages are lost
|
|
||||||
|
|
||||||
|
|
||||||
## Common CBMEM Entry Types
|
|
||||||
|
|
||||||
CBMEM contains various data structures used by different coreboot
|
|
||||||
components:
|
|
||||||
|
|
||||||
- **Console**: Log messages from all boot stages (`CBMEM_ID_CONSOLE`)
|
|
||||||
- **Timestamps**: Performance metrics (`CBMEM_ID_TIMESTAMP`)
|
|
||||||
- **ACPI Tables**: ACPI data for OS handoff (`CBMEM_ID_ACPI`)
|
|
||||||
- **coreboot Tables**: System information (`CBMEM_ID_CBTABLE`)
|
|
||||||
- **Memory Information**: RAM configuration (`CBMEM_ID_MEMINFO`)
|
|
||||||
- **Stage Cache**: Code/data for faster S3 resume
|
|
||||||
- **ROM/CBFS Cache**: Cached ROM content
|
|
||||||
- **Vendor-specific**: Platform-dependent structures
|
|
||||||
|
|
||||||
A complete list of IDs is defined in
|
|
||||||
`src/commonlib/bsd/include/commonlib/bsd/cbmem_id.h`.
|
|
||||||
|
|
||||||
|
|
||||||
## Integration with Boot Stages
|
|
||||||
|
|
||||||
CBMEM interacts differently with each coreboot boot stage.
|
|
||||||
|
|
||||||
|
|
||||||
### Bootblock/Romstage
|
|
||||||
|
|
||||||
- Uses cache-as-RAM for temporary console storage
|
|
||||||
- Limited CBMEM functionality before RAM initialization
|
|
||||||
- Sets up initial timestamp entries
|
|
||||||
|
|
||||||
|
|
||||||
### Ramstage
|
|
||||||
|
|
||||||
- Full CBMEM initialization or recovery
|
|
||||||
- All entries become accessible
|
|
||||||
- Most coreboot subsystems interact with CBMEM
|
|
||||||
- Console logging is fully operational
|
|
||||||
|
|
||||||
|
|
||||||
### Payload Handoff
|
|
||||||
|
|
||||||
- CBMEM contents are preserved when transferring to the payload
|
|
||||||
- Entries are made available via coreboot tables
|
|
||||||
- Common payloads (SeaBIOS, GRUB, etc.) can access CBMEM data
|
|
||||||
|
|
||||||
|
|
||||||
## Platform-Specific Considerations
|
|
||||||
|
|
||||||
Different platforms have unique requirements for CBMEM implementation.
|
|
||||||
|
|
||||||
|
|
||||||
### x86 Platforms
|
|
||||||
|
|
||||||
- CBMEM typically located just below 4GiB
|
|
||||||
- Often integrates with ACPI resume and SMM operations
|
|
||||||
- May need to accommodate memory reserved by legacy components
|
|
||||||
|
|
||||||
|
|
||||||
### ARM/RISC-V Platforms
|
|
||||||
|
|
||||||
- More flexibility in CBMEM placement
|
|
||||||
- Must coordinate with platform-specific memory controllers
|
|
||||||
- Memory topology can vary significantly between implementations
|
|
||||||
|
|
||||||
|
|
||||||
## CBMEM Hooks
|
|
||||||
|
|
||||||
CBMEM provides a hook mechanism to allow subsystems to perform
|
|
||||||
initialization or recovery operations when CBMEM becomes available:
|
|
||||||
|
|
||||||
```c
|
|
||||||
CBMEM_CREATION_HOOK(hook_function); // First-time creation only
|
|
||||||
CBMEM_READY_HOOK(hook_function); // Any CBMEM initialization
|
|
||||||
CBMEM_READY_HOOK_EARLY(hook_function); // Early CBMEM initialization
|
|
||||||
```
|
|
||||||
|
|
||||||
These macros register functions to be called when CBMEM is initialized,
|
|
||||||
allowing components to set up their CBMEM entries at the appropriate time.
|
|
||||||
|
|
||||||
|
|
||||||
## Debugging and Utilities
|
|
||||||
|
|
||||||
### CBMEM Utility
|
|
||||||
|
|
||||||
The `cbmem` utility provides direct access to CBMEM contents on a
|
|
||||||
running system. It needs to be built from the coreboot source tree using
|
|
||||||
`make -C util/cbmem`. Common uses include:
|
|
||||||
|
|
||||||
- Listing all CBMEM entries (`cbmem -l`)
|
|
||||||
- Viewing console logs (`cbmem -c`)
|
|
||||||
- Analyzing timestamps (`cbmem -t`)
|
|
||||||
- Extracting specific entries by ID (`cbmem -e <ID>`)
|
|
||||||
|
|
||||||
|
|
||||||
### Debugging Techniques
|
|
||||||
|
|
||||||
- CBMEM console contents can be dumped to UART for debugging if serial
|
|
||||||
output is enabled.
|
|
||||||
- The console overflow flag (`cbmem -c` output) helps identify if logs
|
|
||||||
were truncated.
|
|
||||||
- Size validation within CBMEM helps detect potential memory corruption.
|
|
||||||
- Magic numbers provide integrity validation for CBMEM structures.
|
|
||||||
- Enabling `CONFIG_CBMEM_CHECKS` in Kconfig adds extra sanity checks
|
|
||||||
that can help catch issues during development.
|
|
||||||
|
|
||||||
|
|
||||||
## Limitations
|
|
||||||
|
|
||||||
While CBMEM is a powerful tool, it has some inherent limitations:
|
|
||||||
|
|
||||||
- **Downward Growth**: The stack-like allocation (growing downwards)
|
|
||||||
means that only the most recently added entry can be removed. This
|
|
||||||
prevents fragmentation but limits flexibility in freeing memory.
|
|
||||||
- **Fixed Size**: Once CBMEM is initialized in ramstage, its total size
|
|
||||||
and top address (`cbmem_top`) are fixed. Entries cannot be resized
|
|
||||||
after allocation.
|
|
||||||
- **Platform Complexity**: Determining the correct `cbmem_top` can be
|
|
||||||
complex on some platforms due to varying memory maps and reserved
|
|
||||||
regions.
|
|
||||||
|
|
||||||
|
|
||||||
## Best Practices for Developers
|
|
||||||
|
|
||||||
When working with the CBMEM subsystem:
|
|
||||||
|
|
||||||
1. **Alignment**: Always respect the alignment requirements of the
|
|
||||||
CBMEM tier (`IMD_ROOT` vs `IMD_SMALL`) you are using.
|
|
||||||
|
|
||||||
2. **ID Selection**: Use unique, meaningful IDs for new entries,
|
|
||||||
preferably encoding ASCII characters for readability (see
|
|
||||||
`cbmem_id.h`).
|
|
||||||
|
|
||||||
3. **Size Estimation**: Allocate sufficient space initially, as
|
|
||||||
entries cannot be resized.
|
|
||||||
|
|
||||||
4. **Memory Conservation**: Be mindful of limited memory resources,
|
|
||||||
especially on constrained platforms. Avoid storing excessively large
|
|
||||||
data structures in CBMEM unless necessary.
|
|
||||||
|
|
||||||
5. **Persistence**: Remember that CBMEM contents persist across
|
|
||||||
warm reboots (like S3 resume) but not across full system resets
|
|
||||||
(cold boots).
|
|
||||||
|
|
||||||
6. **Entry Ordering**: Consider that only the most recently added
|
|
||||||
entry can be removed, which might influence your allocation strategy
|
|
||||||
if you anticipate needing to free space.
|
|
||||||
|
|
@ -84,8 +84,8 @@ the operating system.
|
||||||
|
|
||||||
* U-boot, depthcharge, FILO, etc.
|
* U-boot, depthcharge, FILO, etc.
|
||||||
|
|
||||||
There’s [https://doc.coreboot.org/payloads.html](https://doc.coreboot.org/payloads.html)
|
There’s [https://doc.coreboot.org/payloads.html](https://doc.coreboot.org/payloads.
|
||||||
with a list, although it’s not complete.
|
html) with a list, although it’s not complete.
|
||||||
|
|
||||||
|
|
||||||
### What does coreboot leave in memory after it's done initializing the hardware?
|
### What does coreboot leave in memory after it's done initializing the hardware?
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,7 @@ could cause catastrophic failures, up to and including your mainboard!
|
||||||
As per Intel Platform Controller Hub (PCH) EDS since Skylake, a GPIO PAD register
|
As per Intel Platform Controller Hub (PCH) EDS since Skylake, a GPIO PAD register
|
||||||
supports four different types of GPIO reset as:
|
supports four different types of GPIO reset as:
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------------+----------------+-------------+-------------+
|
+------------------------+----------------+-------------+-------------+
|
||||||
| | | PAD Reset ? |
|
| | | PAD Reset ? |
|
||||||
+ PAD Reset Config + Platform Reset +-------------+-------------+
|
+ PAD Reset Config + Platform Reset +-------------+-------------+
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,10 @@
|
||||||
# Getting Started
|
# Getting Started
|
||||||
|
|
||||||
```{toctree}
|
* [coreboot architecture](architecture.md)
|
||||||
:maxdepth: 1
|
* [Build System](build_system.md)
|
||||||
|
* [Submodules](submodules.md)
|
||||||
coreboot architecture <architecture.md>
|
* [Kconfig](kconfig.md)
|
||||||
Build System <build_system.md>
|
* [Writing Documentation](writing_documentation.md)
|
||||||
Submodules <submodules.md>
|
* [Setting up GPIOs](gpio.md)
|
||||||
Kconfig <kconfig.md>
|
* [Adding devices to a device tree](devicetree.md)
|
||||||
Writing Documentation <writing_documentation.md>
|
* [Frequently Asked Questions](faq.md)
|
||||||
Setting up GPIOs <gpio.md>
|
|
||||||
Adding devices to a device tree <devicetree.md>
|
|
||||||
CBMEM <cbmem.md>
|
|
||||||
Frequently Asked Questions <faq.md>
|
|
||||||
```
|
|
||||||
|
|
|
||||||
|
|
@ -196,9 +196,9 @@ values to be set based on other values.
|
||||||
visible in the front end.
|
visible in the front end.
|
||||||
|
|
||||||
|
|
||||||
### Keywords
|
## Keywords
|
||||||
|
|
||||||
#### bool
|
### bool
|
||||||
|
|
||||||
The 'bool' keyword assigns a boolean type to a symbol. The allowable values for
|
The 'bool' keyword assigns a boolean type to a symbol. The allowable values for
|
||||||
a boolean type are 'n' or 'y'. The keyword can be followed by an optional prompt
|
a boolean type are 'n' or 'y'. The keyword can be followed by an optional prompt
|
||||||
|
|
@ -234,7 +234,7 @@ bool \[prompt\] \[if <expr>\]
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### choice
|
### choice
|
||||||
|
|
||||||
This creates a selection list of one or more boolean symbols. For bools, only
|
This creates a selection list of one or more boolean symbols. For bools, only
|
||||||
one of the symbols can be selected, and one will be be forced to be selected,
|
one of the symbols can be selected, and one will be be forced to be selected,
|
||||||
|
|
@ -297,7 +297,7 @@ choice \[symbol\]
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### comment
|
### comment
|
||||||
|
|
||||||
This keyword defines a line of text that is displayed to the user in the
|
This keyword defines a line of text that is displayed to the user in the
|
||||||
configuration frontend and is additionally written to the output files.
|
configuration frontend and is additionally written to the output files.
|
||||||
|
|
@ -322,7 +322,7 @@ comment <prompt>
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### config
|
### config
|
||||||
|
|
||||||
This is the keyword that starts a block defining a Kconfig symbol. The symbol
|
This is the keyword that starts a block defining a Kconfig symbol. The symbol
|
||||||
modifiers follow the 'config' statement.
|
modifiers follow the 'config' statement.
|
||||||
|
|
@ -359,7 +359,7 @@ config <symbol>
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### default
|
### default
|
||||||
|
|
||||||
The ‘default’ keyword assigns a value to a symbol in the case where no preset
|
The ‘default’ keyword assigns a value to a symbol in the case where no preset
|
||||||
value exists, i.e. the symbol is not present and assigned in .config. If there
|
value exists, i.e. the symbol is not present and assigned in .config. If there
|
||||||
|
|
@ -399,7 +399,7 @@ default <expr> \[if <expr>\]
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### def_bool
|
### def_bool
|
||||||
|
|
||||||
‘def_bool’ is similar to the 'bool' keyword in that it sets a symbol’s type to
|
‘def_bool’ is similar to the 'bool' keyword in that it sets a symbol’s type to
|
||||||
boolean. It lets you set the type and default value at the same time, instead
|
boolean. It lets you set the type and default value at the same time, instead
|
||||||
|
|
@ -433,7 +433,7 @@ def_bool <expr> \[if <expr>\]
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### depends on
|
### depends on
|
||||||
|
|
||||||
This defines a dependency for a menu entry, including symbols and comments. It
|
This defines a dependency for a menu entry, including symbols and comments. It
|
||||||
behaves the same as surrounding the menu entry with an if/endif block. If the
|
behaves the same as surrounding the menu entry with an if/endif block. If the
|
||||||
|
|
@ -462,28 +462,28 @@ depends on <expr>
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### endchoice
|
### endchoice
|
||||||
|
|
||||||
This ends a choice block. See the 'choice' keyword for more information and an
|
This ends a choice block. See the 'choice' keyword for more information and an
|
||||||
example.
|
example.
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### endif
|
### endif
|
||||||
|
|
||||||
This ends a block started by the 'if' keyword. See the 'if' keyword for more
|
This ends a block started by the 'if' keyword. See the 'if' keyword for more
|
||||||
information and an example.
|
information and an example.
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### endmenu
|
### endmenu
|
||||||
|
|
||||||
This ends a menu block. See the 'menu' keyword for more information and an
|
This ends a menu block. See the 'menu' keyword for more information and an
|
||||||
example.
|
example.
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### help
|
### help
|
||||||
|
|
||||||
The 'help' keyword defines the subsequent block of text as help for a config or
|
The 'help' keyword defines the subsequent block of text as help for a config or
|
||||||
choice block. The help block is started by the 'help' keyword on a line by
|
choice block. The help block is started by the 'help' keyword on a line by
|
||||||
|
|
@ -515,7 +515,7 @@ help <help text>
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### hex
|
### hex
|
||||||
|
|
||||||
This is another symbol type specifier, specifying an unsigned integer value
|
This is another symbol type specifier, specifying an unsigned integer value
|
||||||
formatted as hexadecimal.
|
formatted as hexadecimal.
|
||||||
|
|
@ -551,7 +551,7 @@ hex <expr> \[if <expr>\]
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### if
|
### if
|
||||||
|
|
||||||
The 'if' keyword is overloaded, used in two different ways. The first definition
|
The 'if' keyword is overloaded, used in two different ways. The first definition
|
||||||
enables and disables various other keywords, and follows the other keyword
|
enables and disables various other keywords, and follows the other keyword
|
||||||
|
|
@ -592,7 +592,7 @@ endif
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### int
|
### int
|
||||||
|
|
||||||
A type setting keyword, defines a symbol as an integer, accepting only signed
|
A type setting keyword, defines a symbol as an integer, accepting only signed
|
||||||
numeric values. The values can be further restricted with the ‘range’ keyword.
|
numeric values. The values can be further restricted with the ‘range’ keyword.
|
||||||
|
|
@ -628,7 +628,7 @@ int <expr> \[if <expr>\]
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### mainmenu
|
### mainmenu
|
||||||
|
|
||||||
The 'mainmenu' keyword sets the title or title bar of the configuration front
|
The 'mainmenu' keyword sets the title or title bar of the configuration front
|
||||||
end, depending on how the configuration program decides to use it. It can only
|
end, depending on how the configuration program decides to use it. It can only
|
||||||
|
|
@ -648,7 +648,7 @@ mainmenu "coreboot configuration"
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### menu
|
### menu
|
||||||
|
|
||||||
The 'menu' and 'endmenu' keywords tell the configuration front end that the
|
The 'menu' and 'endmenu' keywords tell the configuration front end that the
|
||||||
enclosed statements are part of a group of related pieces.
|
enclosed statements are part of a group of related pieces.
|
||||||
|
|
@ -695,7 +695,7 @@ endmenu
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### prompt
|
### prompt
|
||||||
|
|
||||||
The 'prompt' keyword sets the text displayed for a config symbol or choice in
|
The 'prompt' keyword sets the text displayed for a config symbol or choice in
|
||||||
configuration front end.
|
configuration front end.
|
||||||
|
|
@ -748,7 +748,7 @@ prompt <prompt> \[if <expr>\]
|
||||||
prompt "Prompt value 2"
|
prompt "Prompt value 2"
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### range
|
### range
|
||||||
|
|
||||||
This sets the allowable minimum and maximum entries for hex or int type config
|
This sets the allowable minimum and maximum entries for hex or int type config
|
||||||
symbols.
|
symbols.
|
||||||
|
|
@ -770,7 +770,7 @@ range <symbol> <symbol> \[if <expr>\]
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### select
|
### select
|
||||||
|
|
||||||
The ‘select’ keyword is used within a bool type config block. In coreboot (and
|
The ‘select’ keyword is used within a bool type config block. In coreboot (and
|
||||||
other projects that don't use modules), the 'select' keyword can force an
|
other projects that don't use modules), the 'select' keyword can force an
|
||||||
|
|
@ -814,7 +814,7 @@ select <symbol> \[if <expr>\]
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### source
|
### source
|
||||||
|
|
||||||
The 'source' keyword functions much the same as an 'include' statement in c.
|
The 'source' keyword functions much the same as an 'include' statement in c.
|
||||||
This pulls one or more files into Kconfig at the location of the 'source'
|
This pulls one or more files into Kconfig at the location of the 'source'
|
||||||
|
|
@ -873,7 +873,7 @@ statements that generate a list of all the platform names:
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
#### string
|
### string
|
||||||
|
|
||||||
The last of the symbol type assignment keywords. 'string' allows a text value to
|
The last of the symbol type assignment keywords. 'string' allows a text value to
|
||||||
be entered.
|
be entered.
|
||||||
|
|
@ -919,7 +919,7 @@ keyword later. See the prompt keyword for more notes.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Keywords not used in coreboot at the time of writing:
|
## Keywords not used in coreboot at the time of writing:
|
||||||
|
|
||||||
- allnoconfig_y:
|
- allnoconfig_y:
|
||||||
- defconfig_list
|
- defconfig_list
|
||||||
|
|
@ -944,7 +944,7 @@ statements:
|
||||||
#define SYMBOL NAME XXX
|
#define SYMBOL NAME XXX
|
||||||
|
|
||||||
|
|
||||||
#### Symbol types:
|
##### Symbol types:
|
||||||
- bool, int, and hex types - Every symbol of one of these types created in the
|
- bool, int, and hex types - Every symbol of one of these types created in the
|
||||||
Kconfig tree is defined. It doesn’t matter whether they’re in an if/endif
|
Kconfig tree is defined. It doesn’t matter whether they’re in an if/endif
|
||||||
block, or have a ‘depends on’ statement - they ALL end up being defined in
|
block, or have a ‘depends on’ statement - they ALL end up being defined in
|
||||||
|
|
@ -1164,21 +1164,21 @@ saved .config file. As always, a 'select' statement overrides any specified
|
||||||
|
|
||||||
## Kconfig Editor Highlighting
|
## Kconfig Editor Highlighting
|
||||||
|
|
||||||
### vim:
|
#### vim:
|
||||||
|
|
||||||
vim has syntax highlighting for Kconfig built in (or at least as a part of
|
vim has syntax highlighting for Kconfig built in (or at least as a part of
|
||||||
vim-common), but most editors do not.
|
vim-common), but most editors do not.
|
||||||
|
|
||||||
|
|
||||||
### ultraedit:
|
#### ultraedit:
|
||||||
|
|
||||||
<https://github.com/martinlroth/wordfiles/blob/master/kconfig.uew>
|
https://github.com/martinlroth/wordfiles/blob/master/kconfig.uew
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### atom:
|
#### atom:
|
||||||
|
|
||||||
<https://github.com/martinlroth/language-kconfig>
|
https://github.com/martinlroth/language-kconfig
|
||||||
|
|
||||||
|
|
||||||
## Syntax Checking:
|
## Syntax Checking:
|
||||||
|
|
@ -1217,7 +1217,7 @@ in.
|
||||||
## License:
|
## License:
|
||||||
This work is licensed under the Creative Commons Attribution 4.0 International
|
This work is licensed under the Creative Commons Attribution 4.0 International
|
||||||
License. To view a copy of this license, visit
|
License. To view a copy of this license, visit
|
||||||
<https://creativecommons.org/licenses/by/4.0/> or send a letter to Creative
|
https://creativecommons.org/licenses/by/4.0/ or send a letter to Creative
|
||||||
Commons, PO Box 1866, Mountain View, CA 94042, USA.
|
Commons, PO Box 1866, Mountain View, CA 94042, USA.
|
||||||
|
|
||||||
Code examples snippets are licensed under GPLv2, and are used here under fair
|
Code examples snippets are licensed under GPLv2, and are used here under fair
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,18 @@ coreboot uses [Sphinx] documentation tool. We prefer the markdown format
|
||||||
over reStructuredText so only embedded ReST is supported. Checkout the
|
over reStructuredText so only embedded ReST is supported. Checkout the
|
||||||
[Markdown Guide] for more information.
|
[Markdown Guide] for more information.
|
||||||
|
|
||||||
### Option 1: Use the docker image
|
### option 1: Use the docker image
|
||||||
|
|
||||||
The easiest way to build the documentation is using a docker image.
|
The easiest way to build the documentation is using a docker image.
|
||||||
To build the image run the following in the base directory:
|
To build the image run the following in the base directory:
|
||||||
|
|
||||||
make -C util/docker/ doc.coreboot.org
|
make -C util/docker/ doc.coreboot.org
|
||||||
|
|
||||||
|
Before building the documentation make sure the output directory is given
|
||||||
|
the correct permissions before running docker.
|
||||||
|
|
||||||
|
mkdir -p Documentation/_build
|
||||||
|
|
||||||
To build the documentation:
|
To build the documentation:
|
||||||
|
|
||||||
make -C util/docker docker-build-docs
|
make -C util/docker docker-build-docs
|
||||||
|
|
@ -31,29 +36,31 @@ To have the documentation build and served over a web server live run:
|
||||||
|
|
||||||
On the host machine, open a browser to the address <http://0.0.0.0:8000>.
|
On the host machine, open a browser to the address <http://0.0.0.0:8000>.
|
||||||
|
|
||||||
### Option 2: Install Sphinx
|
### option 2: Install Sphinx
|
||||||
|
|
||||||
Please follow this official [guide] to install sphinx. You will also need
|
Please follow this official [guide] to install sphinx.
|
||||||
myst-parser for sphinx to be able to handle markdown documentation.
|
You will also need python-recommonmark for sphinx to be able to handle
|
||||||
|
markdown documentation.
|
||||||
|
|
||||||
Since some Linux distributions don't package every needed sphinx extension,
|
Since some Linux distributions don't package every needed sphinx extension,
|
||||||
the installation via pip in a venv is recommended. You'll need these python3
|
the installation via pip in a venv is recommended. You'll need these python3
|
||||||
modules:
|
modules:
|
||||||
|
|
||||||
* sphinx
|
* sphinx
|
||||||
* myst-parser
|
* recommonmark
|
||||||
* sphinx-rtd-theme
|
* sphinx_rtd_theme
|
||||||
|
* sphinxcontrib-ditaa
|
||||||
|
|
||||||
The following combination of versions has been tested: sphinx 8.1.3,
|
The following combination of versions has been tested: sphinx 2.3.1,
|
||||||
myst-parser 4.0.0, and sphinx-rtd-theme 2.0.0.
|
recommonmark 0.6.0, sphinx_rtd_theme 0.4.3 and sphinxcontrib-ditaa 0.7.
|
||||||
|
|
||||||
Now change into the `Documentation` folder in the coreboot directory and run
|
Now change into the `Documentation` folder in the coreboot directory and run
|
||||||
this command in there
|
this command in there
|
||||||
|
|
||||||
make
|
make sphinx
|
||||||
|
|
||||||
If no error occurs, you can find the generated HTML documentation in
|
If no error occurs, you can find the generated HTML documentation in
|
||||||
`Documentation/_build/html` now.
|
`Documentation/_build` now.
|
||||||
|
|
||||||
### Optional
|
### Optional
|
||||||
|
|
||||||
|
|
@ -82,19 +89,17 @@ Documentation:
|
||||||
12. Shouldn't cover implementation details; for details, the code is the
|
12. Shouldn't cover implementation details; for details, the code is the
|
||||||
reference.
|
reference.
|
||||||
|
|
||||||
|
## Referencing markdown documents
|
||||||
|
|
||||||
|
Starting with Sphinx 1.6 recommonmark's *auto_doc_ref* feature is broken.
|
||||||
|
To reference documents use the TOC tree or inline RST code.
|
||||||
|
|
||||||
## Markdown and Tables
|
## Markdown and Tables
|
||||||
|
|
||||||
Markdown tables are supported:
|
Under Sphinx markdown tables are not supported. Therefore you can use following
|
||||||
|
code block to write tables in reStructuredText and embed them into the markdown:
|
||||||
|
|
||||||
| Header 1 | Header 2 | Header 3 |
|
```eval_rst
|
||||||
|------------|-----------|-----------|
|
|
||||||
| body row 1 | column 2 | column 3 |
|
|
||||||
| body row 2 | column 2 | column 3 |
|
|
||||||
|
|
||||||
Tables can also be written using embedded reStructured Text, which provides
|
|
||||||
additional features like the ability to merge cells:
|
|
||||||
|
|
||||||
```{eval-rst}
|
|
||||||
+------------+------------+-----------+
|
+------------+------------+-----------+
|
||||||
| Header 1 | Header 2 | Header 3 |
|
| Header 1 | Header 2 | Header 3 |
|
||||||
+============+============+===========+
|
+============+============+===========+
|
||||||
|
|
@ -113,20 +118,22 @@ additional features like the ability to merge cells:
|
||||||
To make sure that all documents are included into the final documentation, you
|
To make sure that all documents are included into the final documentation, you
|
||||||
must reference each document from at least one *toctree*. The *toctree* must
|
must reference each document from at least one *toctree*. The *toctree* must
|
||||||
only reference files in the same folder or in subfolders !
|
only reference files in the same folder or in subfolders !
|
||||||
To create a toctree, you must use the following syntax to invoke the
|
To create a toctree, simply use a bullet list or numbered list with a single
|
||||||
Sphinx toctree directive:
|
reference. References in regular text aren't considered as *toctree* .
|
||||||
|
This feature is enabled by recommonmark's *enable_auto_toc_tree* .
|
||||||
|
|
||||||
**Example toctree:**
|
**Example toctree:**
|
||||||
|
|
||||||
```{toctree}
|
```
|
||||||
:maxdepth: 1
|
* [Chapter 1](chapter1.md)
|
||||||
|
* [Chapter 2](chapter2.md)
|
||||||
|
* [Subchapter](sub/index.md)
|
||||||
|
```
|
||||||
|
|
||||||
Chapter 1 <chapter1.md>
|
```
|
||||||
Chapter 2 <chapter2.md>
|
1. [Chapter 1](chapter1.md)
|
||||||
Subchapter <sub/index.md>
|
2. [Chapter 2](chapter2.md)
|
||||||
```
|
```
|
||||||
|
|
||||||
References in regular text aren't considered as *toctree* .
|
|
||||||
|
|
||||||
If you do only reference the document, but do not include it in any toctree,
|
If you do only reference the document, but do not include it in any toctree,
|
||||||
you'll see the following warning:
|
you'll see the following warning:
|
||||||
|
|
@ -137,7 +144,7 @@ you'll see the following warning:
|
||||||
You can import CSV files and let sphinx automatically convert them to human
|
You can import CSV files and let sphinx automatically convert them to human
|
||||||
readable tables, using the following reStructuredText snipped:
|
readable tables, using the following reStructuredText snipped:
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
.. csv-table::
|
.. csv-table::
|
||||||
:header: "Key", "Value"
|
:header: "Key", "Value"
|
||||||
:file: keyvalues.csv
|
:file: keyvalues.csv
|
||||||
|
|
@ -146,9 +153,11 @@ readable tables, using the following reStructuredText snipped:
|
||||||
Of course this can only be done from a markdown file that is included in the
|
Of course this can only be done from a markdown file that is included in the
|
||||||
TOC tree.
|
TOC tree.
|
||||||
|
|
||||||
[sphinx-autobuild]: https://github.com/sphinx-doc/sphinx-autobuild
|
[coreboot]: https://coreboot.org
|
||||||
[guide]: https://www.sphinx-doc.org/en/master/usage/installation.html
|
[Documentation]: https://review.coreboot.org/cgit/coreboot.git/tree/Documentation
|
||||||
[Sphinx]: https://www.sphinx-doc.org/en/master/
|
[sphinx-autobuild]: https://github.com/GaretJax/sphinx-autobuild
|
||||||
|
[guide]: http://www.sphinx-doc.org/en/stable/install.html
|
||||||
|
[Sphinx]: http://www.sphinx-doc.org/en/master/
|
||||||
[Markdown Guide]: https://www.markdownguide.org/
|
[Markdown Guide]: https://www.markdownguide.org/
|
||||||
[Gerrit Guidelines]: ../contributing/gerrit_guidelines.md
|
[Gerrit Guidelines]: ../contributing/gerrit_guidelines.md
|
||||||
[review.coreboot.org]: https://review.coreboot.org
|
[review.coreboot.org]: https://review.coreboot.org
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ the power sequence timing parameters, which are usually named T[N] and also
|
||||||
referenced in Intel's respective registers listing. You need the values for
|
referenced in Intel's respective registers listing. You need the values for
|
||||||
`PP_ON_DELAYS`, `PP_OFF_DELAYS` and `PP_DIVISOR` for your `devicetree.cb`:
|
`PP_ON_DELAYS`, `PP_OFF_DELAYS` and `PP_DIVISOR` for your `devicetree.cb`:
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+-----------------------------+---------------------------------------+-----+
|
+-----------------------------+---------------------------------------+-----+
|
||||||
| Intel docs | devicetree.cb | eDP |
|
| Intel docs | devicetree.cb | eDP |
|
||||||
+-----------------------------+---------------------------------------+-----+
|
+-----------------------------+---------------------------------------+-----+
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,14 @@ GMA: Framebuffer Configuration
|
||||||
*coreboot* supports two different framebuffer setups. The default
|
*coreboot* supports two different framebuffer setups. The default
|
||||||
enables the legacy VGA plane in textmode. Due to legacy hardware
|
enables the legacy VGA plane in textmode. Due to legacy hardware
|
||||||
constraints, only the first found display is enabled in this mode.
|
constraints, only the first found display is enabled in this mode.
|
||||||
(cf. `src/drivers/intel/gma/text_fb/gma-gfx_init.adb`).
|
(cf. `src/drivers/intel/gma/text_fb/gma.adb`).
|
||||||
|
|
||||||
The second option sets up a high-resolution framebuffer with the
|
The second option sets up a high-resolution framebuffer with the
|
||||||
native resolution of the display if only one is detected, or the
|
native resolution of the display if only one is detected, or the
|
||||||
smallest of all resolutions (per dimension) if multiple displays
|
smallest of all resolutions (per dimension) if multiple displays
|
||||||
are detected. This option is selected by
|
are detected. This option is selected by
|
||||||
`CONFIG_FRAMEBUFFER_KEEP_VESA_MODE`.
|
`CONFIG_FRAMEBUFFER_KEEP_VESA_MODE`.
|
||||||
(cf. `src/drivers/intel/gma/hires_fb/gma-gfx_init.adb`).
|
(cf. `src/drivers/intel/gma/hires_fb/gma.adb`).
|
||||||
|
|
||||||
In any case, a smaller framebuffer is up-scaled to each display's
|
In any case, a smaller framebuffer is up-scaled to each display's
|
||||||
native resolution while keeping aspect ratio.
|
native resolution while keeping aspect ratio.
|
||||||
|
|
|
||||||
|
|
@ -139,45 +139,6 @@ Every now and then, coreboot is present in one way or another at
|
||||||
[conferences](community/conferences.md). If you're around, come and
|
[conferences](community/conferences.md). If you're around, come and
|
||||||
say hello!
|
say hello!
|
||||||
|
|
||||||
## Blob policy in the coreboot project
|
|
||||||
|
|
||||||
The goal of the coreboot project is to provide a FOSS firmware solution across
|
|
||||||
multiple CPU architectures, such as ARM, x86, and RISC-V. While fully open
|
|
||||||
source implementations for these architectures are encouraged and preferred,
|
|
||||||
we understand that a fully open implementation whereby every firmware component
|
|
||||||
is available as source code for modern platforms is not always feasible.
|
|
||||||
Different reasons inhibit the availability of fully open implementations,
|
|
||||||
including limited development resources, 3rd party license constraints of
|
|
||||||
IP blocks, or a legacy mindset of the silicon vendors.
|
|
||||||
|
|
||||||
It is important for the coreboot project to have support for modern CPU
|
|
||||||
platforms in order to provide a viable alternative for proprietary firmware
|
|
||||||
implementations. We do not have direct control over how hardware vendors design
|
|
||||||
their products, however we can provide an attractive alternative to the
|
|
||||||
expensive and complicated proprietary firmware model that exists today.
|
|
||||||
For modern platforms, we are largely dependent on the silicon
|
|
||||||
vendor to provide additional information on how to properly initialize the
|
|
||||||
hardware, as the required datasheets are often only available with an NDA.
|
|
||||||
Therefore, one possible way to have coreboot support for the latest platforms
|
|
||||||
is binary code (aka, a blob) provided by the silicon vendor. While we do
|
|
||||||
discourage this solution, it can be a door opener for coreboot’s support of a
|
|
||||||
given platform and thus keep coreboot functional on modern platforms. It is
|
|
||||||
clearly not the goal of the project to accept every blob a silicon vendor wishes
|
|
||||||
to use without question. On the contrary, each new blob needs to be examined
|
|
||||||
critically by the community, evaluating the need, risk, and alternative options.
|
|
||||||
|
|
||||||
Wherever possible, introducing new blobs should be avoided. That said, there
|
|
||||||
can be situations where a piece of code provided as a blob will enable the rest
|
|
||||||
of the fully open source firmware stack on a brand new platform. If blocking
|
|
||||||
this blob would lead to no support at all for the platform in question in
|
|
||||||
coreboot, this situation needs to be examined carefully. While these kinds
|
|
||||||
of discussion will be coordinated closely with the community (e.g. on the
|
|
||||||
mailing list or dedicated meetings), ultimately it is up to the leadership to
|
|
||||||
decide if there is no agreement between the community and the vendor pushing for
|
|
||||||
the new blob. This decision will be communicated on the mailing list.
|
|
||||||
Please see additionally
|
|
||||||
[coreboot binary policy](https://github.com/coreboot/blobs/blob/master/README.md).
|
|
||||||
|
|
||||||
## Getting the source code
|
## Getting the source code
|
||||||
|
|
||||||
coreboot is primarily developed in the
|
coreboot is primarily developed in the
|
||||||
|
|
@ -209,39 +170,34 @@ for example OpenBSD, is probably the closest cousin of our approach.
|
||||||
|
|
||||||
Contents:
|
Contents:
|
||||||
|
|
||||||
```{toctree}
|
* [Getting Started](getting_started/index.md)
|
||||||
:maxdepth: 1
|
* [Tutorial](tutorial/index.md)
|
||||||
|
* [Contributing](contributing/index.md)
|
||||||
Getting Started <getting_started/index.md>
|
* [Community](community/index.md)
|
||||||
Tutorial <tutorial/index.md>
|
* [Payloads](payloads.md)
|
||||||
Contributing <contributing/index.md>
|
* [Distributions](distributions.md)
|
||||||
Community <community/index.md>
|
* [Technotes](technotes/index.md)
|
||||||
Payloads <payloads.md>
|
* [ACPI](acpi/index.md)
|
||||||
Distributions <distributions.md>
|
* [Native Graphics Initialization with libgfxinit](gfx/libgfxinit.md)
|
||||||
Technotes <technotes/index.md>
|
* [Display panel](gfx/display-panel.md)
|
||||||
Internal APIs & Configuration <internals/index.md>
|
* [CPU Architecture](arch/index.md)
|
||||||
ACPI <acpi/index.md>
|
* [Platform independent drivers](drivers/index.md)
|
||||||
Native Graphics Initialization with libgfxinit <gfx/libgfxinit.md>
|
* [Northbridge](northbridge/index.md)
|
||||||
Display panel <gfx/display-panel.md>
|
* [System on Chip](soc/index.md)
|
||||||
CPU Architecture <arch/index.md>
|
* [Mainboard](mainboard/index.md)
|
||||||
Platform independent drivers <drivers/index.md>
|
* [Payloads](lib/payloads/index.md)
|
||||||
Northbridge <northbridge/index.md>
|
* [Libraries](lib/index.md)
|
||||||
System on Chip <soc/index.md>
|
* [Options](lib/option.md)
|
||||||
Mainboard <mainboard/index.md>
|
* [Security](security/index.md)
|
||||||
Payloads <lib/payloads/index.md>
|
* [SuperIO](superio/index.md)
|
||||||
Libraries <lib/index.md>
|
* [Vendorcode](vendorcode/index.md)
|
||||||
Options <lib/option.md>
|
* [Utilities](util.md)
|
||||||
Security <security/index.md>
|
* [Software Bill of Materials](sbom/sbom.md)
|
||||||
SuperIO <superio/index.md>
|
* [Project infrastructure & services](infrastructure/index.md)
|
||||||
Vendorcode <vendorcode/index.md>
|
* [Boards supported in each release directory](releases/boards_supported_on_branches.md)
|
||||||
Utilities <util.md>
|
* [Release notes](releases/index.md)
|
||||||
Software Bill of Materials <sbom/sbom.md>
|
* [Acronyms & Definitions](acronyms.md)
|
||||||
Project infrastructure & services <infrastructure/index.md>
|
* [External Resources](external_docs.md)
|
||||||
Boards supported in each release directory <releases/boards_supported_on_branches.md>
|
* [Documentation License](documentation_license.md)
|
||||||
Release notes <releases/index.md>
|
|
||||||
Acronyms & Definitions <acronyms.md>
|
|
||||||
External Resources <external_docs.md>
|
|
||||||
Documentation License <documentation_license.md>
|
|
||||||
```
|
|
||||||
|
|
||||||
[Documentation]: https://review.coreboot.org/plugins/gitiles/coreboot/+/refs/heads/main/Documentation/
|
[Documentation]: https://review.coreboot.org/plugins/gitiles/coreboot/+/refs/heads/main/Documentation/
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ as the system can just be disabled until someone is available to fix any
|
||||||
issues.
|
issues.
|
||||||
|
|
||||||
Currently active Jenkins admins:
|
Currently active Jenkins admins:
|
||||||
|
* Patrick Georgi:
|
||||||
|
* Email: [patrick@coreboot.org](mailto:patrick@coreboot.org)
|
||||||
* Martin Roth:
|
* Martin Roth:
|
||||||
* Email: [gaumless@gmail.com](mailto:gaumless@gmail.com)
|
* Email: [gaumless@gmail.com](mailto:gaumless@gmail.com)
|
||||||
* IRC: martinr
|
* IRC: martinr
|
||||||
|
|
|
||||||
|
|
@ -100,4 +100,4 @@ are discovered and go unnoticed in a later build.
|
||||||
|
|
||||||
More projects that are hosted on review.coreboot.org (potentially as a
|
More projects that are hosted on review.coreboot.org (potentially as a
|
||||||
mirror, like vboot and EC) could be served through that pipeline. Reach
|
mirror, like vboot and EC) could be served through that pipeline. Reach
|
||||||
out to {stepan,martin}@coreboot.org.
|
out to {stepan,patrick,martin}@coreboot.org.
|
||||||
|
|
|
||||||
|
|
@ -4,17 +4,9 @@ This section contains documentation about our infrastructure
|
||||||
|
|
||||||
## Services
|
## Services
|
||||||
|
|
||||||
```{toctree}
|
* [Project services](services.md)
|
||||||
:maxdepth: 1
|
* [Administrator's handbook](admin.md)
|
||||||
|
|
||||||
Project services <services.md>
|
|
||||||
Administrator's handbook <admin.md>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Jenkins builders and builds
|
## Jenkins builders and builds
|
||||||
```{toctree}
|
* [Setting up Jenkins build machines](builders.md)
|
||||||
:maxdepth: 1
|
* [Coverity Scan integration](coverity.md)
|
||||||
|
|
||||||
Setting up Jenkins build machines <builders.md>
|
|
||||||
Coverity Scan integration <coverity.md>
|
|
||||||
```
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ stating:
|
||||||
|
|
||||||
### Gerrit user avatar
|
### Gerrit user avatar
|
||||||
To setup an avatar to show in Gerrit, clone the avatars repository at
|
To setup an avatar to show in Gerrit, clone the avatars repository at
|
||||||
<https://review.coreboot.org/gerrit-avatars.git> and add a file named
|
https://review.coreboot.org/gerrit-avatars.git and add a file named
|
||||||
$your-user-ID.jpg (the user ID is a number shown on the [settings screen](https://review.coreboot.org/settings)).
|
$your-user-ID.jpg (the user ID is a number shown on the [settings screen](https://review.coreboot.org/settings)).
|
||||||
The image must be provided in JPEG format, must be square and have at most 50000
|
The image must be provided in JPEG format, must be square and have at most 50000
|
||||||
bytes.
|
bytes.
|
||||||
|
|
|
||||||
|
|
@ -1,537 +0,0 @@
|
||||||
# The `chip_operations` Structure in coreboot
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
|
|
||||||
The `chip_operations` structure is a fundamental component of coreboot's
|
|
||||||
chipset abstraction layer. It provides a standardized interface for chipset-
|
|
||||||
specific code to interact with coreboot's device initialization framework.
|
|
||||||
This structure enables coreboot to support a wide variety of chipsets
|
|
||||||
while maintaining a consistent initialization flow across different hardware
|
|
||||||
platforms.
|
|
||||||
|
|
||||||
In coreboot's architecture, a "chip" refers to a collection of hardware
|
|
||||||
components that form a logical unit, such as a System-on-Chip (SoC),
|
|
||||||
a CPU, or a distinct southbridge/northbridge. The `chip_operations`
|
|
||||||
structure provides the hooks necessary for coreboot to discover, configure,
|
|
||||||
and initialize these components during the boot process.
|
|
||||||
|
|
||||||
The `chip_operations` structure is particularly crucial for the ramstage
|
|
||||||
portion of coreboot, where it connects the static device tree definitions
|
|
||||||
with the actual hardware initialization code. It serves as the bridge
|
|
||||||
between the declarative device descriptions and the imperative code that
|
|
||||||
brings those devices to life.
|
|
||||||
|
|
||||||
|
|
||||||
## Structure Definition
|
|
||||||
|
|
||||||
The `chip_operations` structure is defined in `src/include/device/device.h`
|
|
||||||
as follows:
|
|
||||||
|
|
||||||
```c
|
|
||||||
struct chip_operations {
|
|
||||||
void (*enable_dev)(struct device *dev);
|
|
||||||
void (*init)(void *chip_info);
|
|
||||||
void (*final)(void *chip_info);
|
|
||||||
unsigned int initialized : 1;
|
|
||||||
unsigned int finalized : 1;
|
|
||||||
const char *name;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Field Descriptions
|
|
||||||
|
|
||||||
- **enable_dev**: A function pointer that takes a `struct device*`
|
|
||||||
parameter. This function is called for each device associated with the
|
|
||||||
chip during the device enumeration phase (specifically, within the
|
|
||||||
`scan_bus` operations triggered by `dev_enumerate`). Its primary
|
|
||||||
purpose is to set up device operations (`dev->ops`) based on the
|
|
||||||
device's role in the system.
|
|
||||||
|
|
||||||
- **init**: A function pointer that takes a `void*` parameter pointing to
|
|
||||||
the chip's configuration data (typically cast to a chip-specific struct).
|
|
||||||
This function is called during the chip initialization phase
|
|
||||||
(`BS_DEV_INIT_CHIPS`), before device enumeration. It usually performs
|
|
||||||
early hardware setup needed before individual devices can be configured.
|
|
||||||
|
|
||||||
- **final**: A function pointer that takes a `void*` parameter pointing to
|
|
||||||
the chip's configuration data (typically cast to a chip-specific struct).
|
|
||||||
This function is called during the final table writing phase of coreboot
|
|
||||||
initialization (`BS_WRITE_TABLES`), after all devices have been
|
|
||||||
initialized. It performs any necessary cleanup or late initialization
|
|
||||||
operations.
|
|
||||||
|
|
||||||
- **initialized**: A bit flag indicating whether the chip's init function
|
|
||||||
has been called.
|
|
||||||
|
|
||||||
- **finalized**: A bit flag indicating whether the chip's final function
|
|
||||||
has been called.
|
|
||||||
|
|
||||||
- **name**: A string containing the human-readable name of the chip, used
|
|
||||||
for debugging and logging purposes.
|
|
||||||
|
|
||||||
|
|
||||||
## Initialization Sequence and `chip_operations`
|
|
||||||
|
|
||||||
The `chip_operations` structure integrates with coreboot's boot state
|
|
||||||
machine, which is defined in `src/lib/hardwaremain.c`. The functions in
|
|
||||||
this structure are called at specific points during the boot process:
|
|
||||||
|
|
||||||
1. **BS_DEV_INIT_CHIPS** state: The `init` function is called for each
|
|
||||||
chip in the device tree. This is handled by `dev_initialize_chips()`
|
|
||||||
which iterates through all devices, identifies unique chip instances,
|
|
||||||
and invokes their `init` functions.
|
|
||||||
|
|
||||||
2. **BS_DEV_ENUMERATE** state: During the execution of this state,
|
|
||||||
`dev_enumerate()` is called, which triggers bus scanning
|
|
||||||
(e.g., `pci_scan_bus`). Within these scan routines, the `enable_dev`
|
|
||||||
function is called for devices associated with a chip. This commonly
|
|
||||||
assigns the appropriate `device_operations` structure to each device
|
|
||||||
based on its type and purpose.
|
|
||||||
|
|
||||||
3. **BS_WRITE_TABLES** state: The `final` function is called for each
|
|
||||||
chip by `dev_finalize_chips()` after all devices have been initialized
|
|
||||||
and just before payloads are loaded.
|
|
||||||
|
|
||||||
This sequence ensures that chips can perform necessary setup before their
|
|
||||||
individual devices are configured, and also perform cleanup or finalization
|
|
||||||
after all devices have been initialized but before the final tables are
|
|
||||||
written and the payload is executed.
|
|
||||||
|
|
||||||
|
|
||||||
## Relationship Between `chip_operations` and `device_operations`
|
|
||||||
|
|
||||||
It's important to understand the distinction and relationship between
|
|
||||||
`chip_operations` and `device_operations`:
|
|
||||||
|
|
||||||
- **chip_operations**: Operates at the chipset or SoC level, providing
|
|
||||||
hooks for chip-wide initialization. It's responsible for the overall
|
|
||||||
setup of a collection of devices that belong to the same logical chip.
|
|
||||||
|
|
||||||
- **device_operations**: Operates at the individual device level,
|
|
||||||
providing functions to manage specific devices within a chip. These
|
|
||||||
operations include resource allocation, device initialization, and device-
|
|
||||||
specific functionality.
|
|
||||||
|
|
||||||
The key relationship is that `chip_operations.enable_dev` is typically
|
|
||||||
responsible for assigning the appropriate `device_operations` structure
|
|
||||||
to each device based on its type and function. This is where the bridge
|
|
||||||
between the chip-level and device-level abstractions occurs.
|
|
||||||
|
|
||||||
For example, a typical implementation of the `enable_dev` function might
|
|
||||||
look like this:
|
|
||||||
|
|
||||||
```c
|
|
||||||
static void soc_enable(struct device *dev)
|
|
||||||
{
|
|
||||||
if (dev->path.type == DEVICE_PATH_DOMAIN)
|
|
||||||
dev->ops = &pci_domain_ops;
|
|
||||||
else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER)
|
|
||||||
dev->ops = &cpu_bus_ops;
|
|
||||||
else if (dev->path.type == DEVICE_PATH_GPIO)
|
|
||||||
block_gpio_enable(dev);
|
|
||||||
else if (dev->path.type == DEVICE_PATH_PCI &&
|
|
||||||
dev->path.pci.devfn == PCH_DEVFN_PMC)
|
|
||||||
dev->ops = &pmc_ops;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This function examines each device's path type and assigns the appropriate
|
|
||||||
operations based on the device's role in the system.
|
|
||||||
|
|
||||||
|
|
||||||
## Integration with the Devicetree
|
|
||||||
|
|
||||||
The `chip_operations` structure is tightly integrated with coreboot's
|
|
||||||
devicetree mechanism. The devicetree is a hierarchical description of the
|
|
||||||
hardware platform, defined in `.cb` files (typically `chipset.cb`,
|
|
||||||
`devicetree.cb`, and optionally `overridetree.cb`).
|
|
||||||
|
|
||||||
In the devicetree, a `chip` directive starts a collection of devices
|
|
||||||
associated with a particular chip driver. The path specified with the
|
|
||||||
`chip` directive corresponds to a directory in the coreboot source tree
|
|
||||||
that contains the chip driver code, including a `chip.c` file that defines
|
|
||||||
the `chip_operations` structure for that chip.
|
|
||||||
|
|
||||||
For example, a devicetree might contain:
|
|
||||||
|
|
||||||
```
|
|
||||||
chip soc/intel/cannonlake
|
|
||||||
device domain 0 on
|
|
||||||
device pci 00.0 on end # Host Bridge
|
|
||||||
device pci 12.0 on end # Thermal Subsystem
|
|
||||||
# ... more devices ...
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
This connects the devices under this chip directive with the
|
|
||||||
`chip_operations` structure defined in
|
|
||||||
`src/soc/intel/cannonlake/chip.c`:
|
|
||||||
|
|
||||||
```c
|
|
||||||
struct chip_operations soc_intel_cannonlake_ops = {
|
|
||||||
.name = "Intel Cannonlake",
|
|
||||||
.enable_dev = &soc_enable,
|
|
||||||
.init = &soc_init_pre_device,
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
During coreboot's build process, the `sconfig` utility processes the
|
|
||||||
devicetree files and generates code that links the devices defined in the
|
|
||||||
devicetree with their corresponding `chip_operations` structures.
|
|
||||||
|
|
||||||
|
|
||||||
## Chip Configuration Data
|
|
||||||
|
|
||||||
Each chip typically defines a configuration structure in a `chip.h` file
|
|
||||||
within its source directory. This structure contains configuration settings
|
|
||||||
that can be specified in the devicetree using `register` directives.
|
|
||||||
|
|
||||||
For example, a chip might define a configuration structure like:
|
|
||||||
|
|
||||||
```c
|
|
||||||
/* In src/soc/intel/cannonlake/chip.h */
|
|
||||||
struct soc_intel_cannonlake_config {
|
|
||||||
uint8_t pcie_rp_aspm[CONFIG_MAX_ROOT_PORTS];
|
|
||||||
uint8_t usb2_ports[16];
|
|
||||||
uint8_t usb3_ports[10];
|
|
||||||
/* ... more configuration options ... */
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
In the devicetree, you would configure these options using register
|
|
||||||
directives:
|
|
||||||
|
|
||||||
```
|
|
||||||
chip soc/intel/cannonlake
|
|
||||||
register "pcie_rp_aspm[0]" = "ASPM_AUTO"
|
|
||||||
register "usb2_ports[5]" = "USB2_PORT_MID(OC_SKIP)"
|
|
||||||
# ... more register settings ...
|
|
||||||
|
|
||||||
device domain 0 on
|
|
||||||
# ... devices ...
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
These configuration values are made available to the chip's `init` and
|
|
||||||
`final` functions through the `chip_info` parameter, which points to
|
|
||||||
an instance of the chip's configuration structure (after appropriate
|
|
||||||
casting from `void *`).
|
|
||||||
|
|
||||||
|
|
||||||
## Implementation Examples
|
|
||||||
|
|
||||||
### Minimal Implementation
|
|
||||||
|
|
||||||
Some chips may not need extensive initialization and can provide a
|
|
||||||
minimal implementation of the `chip_operations` structure:
|
|
||||||
|
|
||||||
```c
|
|
||||||
struct chip_operations soc_ucb_riscv_ops = {
|
|
||||||
.name = "UCB RISC-V",
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
This implementation only provides a name for debugging purposes but
|
|
||||||
doesn't define any initialization functions.
|
|
||||||
|
|
||||||
|
|
||||||
### Basic Implementation with Initialization
|
|
||||||
|
|
||||||
A more typical implementation includes at least initialization hooks:
|
|
||||||
|
|
||||||
```c
|
|
||||||
struct chip_operations soc_amd_genoa_poc_ops = {
|
|
||||||
.name = "AMD Genoa SoC Proof of Concept",
|
|
||||||
.init = soc_init,
|
|
||||||
.final = soc_final,
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
The `init` function might perform chip-wide initialization:
|
|
||||||
|
|
||||||
```c
|
|
||||||
static void soc_init(void *chip_info)
|
|
||||||
{
|
|
||||||
default_dev_ops_root.write_acpi_tables = soc_acpi_write_tables;
|
|
||||||
amd_opensil_silicon_init();
|
|
||||||
data_fabric_print_mmio_conf();
|
|
||||||
fch_init(chip_info);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Complete Implementation
|
|
||||||
|
|
||||||
A complete implementation includes all three function pointers:
|
|
||||||
|
|
||||||
```c
|
|
||||||
struct chip_operations soc_intel_xeon_sp_cpx_ops = {
|
|
||||||
.name = "Intel Cooper Lake-SP",
|
|
||||||
.enable_dev = chip_enable_dev,
|
|
||||||
.init = chip_init,
|
|
||||||
.final = chip_final,
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
The `enable_dev` function would typically assign device operations
|
|
||||||
based on device types:
|
|
||||||
|
|
||||||
```c
|
|
||||||
static void chip_enable_dev(struct device *dev)
|
|
||||||
{
|
|
||||||
/* PCI root complex */
|
|
||||||
if (dev->path.type == DEVICE_PATH_DOMAIN)
|
|
||||||
dev->ops = &pci_domain_ops;
|
|
||||||
/* CPU cluster */
|
|
||||||
else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER)
|
|
||||||
dev->ops = &cpu_cluster_ops;
|
|
||||||
/* PCIe root ports */
|
|
||||||
else if (dev->path.type == DEVICE_PATH_PCI &&
|
|
||||||
PCI_SLOT(dev->path.pci.devfn) == PCIE_PORT1_SLOT)
|
|
||||||
dev->ops = &pcie_rp_ops;
|
|
||||||
/* ... other device types ... */
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Mainboard Implementation
|
|
||||||
|
|
||||||
It's also common for the mainboard-specific code (e.g.,
|
|
||||||
`src/mainboard/vendor/board/mainboard.c`) to define its own
|
|
||||||
`chip_operations`, often named `mainboard_ops`. The `mainboard_ops.init`
|
|
||||||
can perform early board-level setup, and `mainboard_ops.enable_dev` can
|
|
||||||
assign operations for devices specific to the mainboard or set default
|
|
||||||
operations.
|
|
||||||
|
|
||||||
```c
|
|
||||||
/* Example from src/mainboard/google/zork/mainboard.c */
|
|
||||||
struct chip_operations mainboard_ops = {
|
|
||||||
.enable_dev = mainboard_enable,
|
|
||||||
.init = mainboard_init,
|
|
||||||
.final = mainboard_final,
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Device Registration and Discovery
|
|
||||||
|
|
||||||
The `chip_operations` structure plays a key role in device registration
|
|
||||||
and discovery within coreboot. Here's how it fits into this process:
|
|
||||||
|
|
||||||
1. **Static Device Definition**: Devices are statically defined in the
|
|
||||||
devicetree files (`chipset.cb`, `devicetree.cb`, `overridetree.cb`).
|
|
||||||
|
|
||||||
2. **Code Generation**: The `sconfig` utility processes these files and
|
|
||||||
generates code in `build/static.c` that creates the device structures
|
|
||||||
and links them to their corresponding chip configuration data.
|
|
||||||
|
|
||||||
3. **Chip Initialization**: During the `BS_DEV_INIT_CHIPS` boot state,
|
|
||||||
`dev_initialize_chips()` calls each chip's `init` function to perform
|
|
||||||
chip-wide setup.
|
|
||||||
|
|
||||||
4. **Device Enumeration and Enabling**: During the `BS_DEV_ENUMERATE`
|
|
||||||
boot state, `dev_enumerate()` initiates bus scanning. The scan
|
|
||||||
functions call the associated chip's `enable_dev` function for each
|
|
||||||
device, which assigns the appropriate device operations (`dev->ops`).
|
|
||||||
|
|
||||||
5. **Device Configuration and Initialization**: Subsequent boot states
|
|
||||||
(`BS_DEV_RESOURCES`, `BS_DEV_ENABLE`, `BS_DEV_INIT`) configure and
|
|
||||||
initialize the devices according to their assigned device operations.
|
|
||||||
|
|
||||||
6. **Chip Finalization**: After all devices have been initialized,
|
|
||||||
`dev_finalize_chips()` calls each chip's `final` function during the
|
|
||||||
`BS_WRITE_TABLES` boot state.
|
|
||||||
|
|
||||||
|
|
||||||
## Build Process Integration
|
|
||||||
|
|
||||||
The `chip_operations` structures are integrated into the coreboot build
|
|
||||||
process through several mechanisms:
|
|
||||||
|
|
||||||
1. **Devicetree Processing**: The `sconfig` utility processes the
|
|
||||||
devicetree files and generates code that creates and links the device
|
|
||||||
structures.
|
|
||||||
|
|
||||||
2. **Static Structure Declaration**: Each chip (and often the mainboard)
|
|
||||||
defines its `chip_operations` structure in its respective `.c` file.
|
|
||||||
These structures are collected during the build process.
|
|
||||||
|
|
||||||
3. **External References**: The generated code in `build/static.c`
|
|
||||||
includes external references to these `chip_operations` structures.
|
|
||||||
|
|
||||||
4. **Linking**: The linker collects all the `chip_operations` structures
|
|
||||||
and includes them in the final firmware image.
|
|
||||||
|
|
||||||
This process ensures that the appropriate chip operations are available
|
|
||||||
during the boot process for each chip included in the devicetree.
|
|
||||||
|
|
||||||
|
|
||||||
## Best Practices for Implementing `chip_operations`
|
|
||||||
|
|
||||||
When implementing the `chip_operations` structure for a new chip,
|
|
||||||
follow these best practices:
|
|
||||||
|
|
||||||
1. **Provide a Meaningful Name**: The `name` field should be descriptive
|
|
||||||
and identify the chip clearly for debugging purposes.
|
|
||||||
|
|
||||||
2. **Implement `enable_dev` Correctly**: The `enable_dev` function should
|
|
||||||
assign the appropriate device operations based on device types and
|
|
||||||
functions. It should handle all device types that might be part of the chip.
|
|
||||||
Consider interactions with the mainboard `enable_dev`.
|
|
||||||
|
|
||||||
3. **Use Configuration Data**: The `init` and `final` functions should
|
|
||||||
make use of the chip configuration data passed via the `chip_info`
|
|
||||||
parameter (casting it to the correct type) to configure the chip
|
|
||||||
according to the settings specified in the devicetree.
|
|
||||||
|
|
||||||
4. **Minimize Dependencies**: The `init` function should minimize
|
|
||||||
dependencies on other chips being initialized, as the order of chip
|
|
||||||
initialization is not guaranteed.
|
|
||||||
|
|
||||||
5. **Handle Resources Properly**: If the chip manages resources (memory
|
|
||||||
regions, I/O ports, etc.), ensure that these are properly allocated and
|
|
||||||
assigned to devices, usually within the associated `device_operations`.
|
|
||||||
|
|
||||||
6. **Implement Error Handling**: Include appropriate error handling in
|
|
||||||
the initialization functions to handle hardware initialization failures
|
|
||||||
gracefully.
|
|
||||||
|
|
||||||
7. **Document Special Requirements**: If the chip has special
|
|
||||||
requirements or dependencies, document these clearly in comments or
|
|
||||||
accompanying documentation.
|
|
||||||
|
|
||||||
|
|
||||||
## Troubleshooting `chip_operations` Issues
|
|
||||||
|
|
||||||
When implementing or debugging `chip_operations`, you might encounter
|
|
||||||
certain issues:
|
|
||||||
|
|
||||||
1. **Missing Device Operations**: If devices are not being initialized
|
|
||||||
properly, check that the `enable_dev` function is correctly
|
|
||||||
assigning device operations based on device types. Ensure it's being
|
|
||||||
called during bus scanning.
|
|
||||||
|
|
||||||
2. **Initialization Order Problems**: If a chip's initialization depends
|
|
||||||
on another chip being initialized first, you might need to adjust the
|
|
||||||
initialization sequence or add explicit dependencies, possibly using
|
|
||||||
boot state callbacks if necessary.
|
|
||||||
|
|
||||||
3. **Configuration Data Issues**: If chip configuration settings are not
|
|
||||||
being applied correctly, check that the configuration structure is
|
|
||||||
correctly defined in `chip.h`, that the register values in the
|
|
||||||
devicetree match the expected format, and that the `chip_info` pointer
|
|
||||||
is cast correctly in the `init`/`final` functions.
|
|
||||||
|
|
||||||
4. **Build Errors**: If you encounter build errors related to
|
|
||||||
`chip_operations`, check that the structure is correctly defined and
|
|
||||||
that all required symbols are properly exported and linked. Check for
|
|
||||||
conflicts if multiple files define the same symbol.
|
|
||||||
|
|
||||||
5. **Runtime Failures**: If the chip initialization fails at runtime,
|
|
||||||
add debug logging (using `printk`) to the `init`, `enable_dev`, and
|
|
||||||
`final` functions to identify the specific point of failure.
|
|
||||||
|
|
||||||
|
|
||||||
## Advanced `chip_operations` Patterns
|
|
||||||
|
|
||||||
### Hierarchical Chip Initialization
|
|
||||||
|
|
||||||
For complex chips with multiple components, you can implement a
|
|
||||||
hierarchical initialization pattern within the `init` function:
|
|
||||||
|
|
||||||
```c
|
|
||||||
static void soc_init(void *chip_info)
|
|
||||||
{
|
|
||||||
/* Initialize common components first */
|
|
||||||
common_init(chip_info);
|
|
||||||
|
|
||||||
/* Initialize specific blocks */
|
|
||||||
pcie_init(chip_info);
|
|
||||||
usb_init(chip_info);
|
|
||||||
sata_init(chip_info);
|
|
||||||
|
|
||||||
/* Final SoC-wide configuration */
|
|
||||||
power_management_init(chip_info);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Variant Support
|
|
||||||
|
|
||||||
For chips with multiple variants, you can implement variant detection
|
|
||||||
and specific initialization within the `init` function:
|
|
||||||
|
|
||||||
```c
|
|
||||||
static void soc_init(void *chip_info)
|
|
||||||
{
|
|
||||||
uint32_t variant = read_chip_variant();
|
|
||||||
|
|
||||||
/* Common initialization */
|
|
||||||
common_init(chip_info);
|
|
||||||
|
|
||||||
/* Variant-specific initialization */
|
|
||||||
switch (variant) {
|
|
||||||
case VARIANT_A:
|
|
||||||
variant_a_init(chip_info);
|
|
||||||
break;
|
|
||||||
case VARIANT_B:
|
|
||||||
variant_b_init(chip_info);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printk(BIOS_WARNING, "Unknown variant %u\\n", variant);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Conditional Feature Initialization
|
|
||||||
|
|
||||||
You can conditionally initialize features based on configuration settings
|
|
||||||
passed via `chip_info`:
|
|
||||||
|
|
||||||
```c
|
|
||||||
static void soc_init(void *chip_info)
|
|
||||||
{
|
|
||||||
struct soc_config *config = chip_info;
|
|
||||||
|
|
||||||
/* Always initialize core components */
|
|
||||||
core_init();
|
|
||||||
|
|
||||||
/* Conditionally initialize optional features */
|
|
||||||
if (config->enable_xhci)
|
|
||||||
xhci_init(config);
|
|
||||||
|
|
||||||
if (config->enable_sata)
|
|
||||||
sata_init(config);
|
|
||||||
|
|
||||||
if (config->enable_pcie)
|
|
||||||
pcie_init(config);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
The `chip_operations` structure is a fundamental component of coreboot's
|
|
||||||
chipset abstraction layer. It provides a standardized interface for chipset-
|
|
||||||
specific code to interact with coreboot's device initialization framework,
|
|
||||||
enabling support for a wide variety of chipsets while maintaining a
|
|
||||||
consistent initialization flow.
|
|
||||||
|
|
||||||
By implementing the `chip_operations` structure for a specific chipset
|
|
||||||
(and often for the mainboard), developers can integrate their
|
|
||||||
hardware-specific code with coreboot's device enumeration, configuration,
|
|
||||||
and initialization process. This structure serves as the bridge between
|
|
||||||
the declarative device descriptions in the devicetree and the imperative
|
|
||||||
code that initializes the hardware.
|
|
||||||
|
|
||||||
Understanding the `chip_operations` structure and its role in the
|
|
||||||
coreboot boot process is essential for anyone working on chipset or
|
|
||||||
mainboard support in coreboot. By following the best practices and
|
|
||||||
patterns outlined in this document, developers can create robust and
|
|
||||||
maintainable hardware support code that integrates seamlessly with the
|
|
||||||
coreboot firmware ecosystem.
|
|
||||||
|
|
@ -1,696 +0,0 @@
|
||||||
# Device Operations in coreboot Firmware
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
|
|
||||||
The `device_operations` structure is a cornerstone of coreboot's
|
|
||||||
hardware abstraction layer. It represents a set of function pointers
|
|
||||||
defining how the firmware interacts with a specific hardware device
|
|
||||||
during various boot stages. This structure lets the coreboot
|
|
||||||
architecture establish a consistent interface for device initialization,
|
|
||||||
configuration, resource allocation, and ACPI table generation, while
|
|
||||||
allowing device-specific implementations behind this common interface.
|
|
||||||
|
|
||||||
At its core, `device_operations` applies the strategy pattern in
|
|
||||||
systems programming. It decouples algorithms (device operations) from
|
|
||||||
the core boot sequence, allowing devices to define their own behavior
|
|
||||||
while the boot process follows a predictable flow. This pattern enables
|
|
||||||
coreboot to support a wide range of hardware platforms with minimal
|
|
||||||
changes to the core boot sequence code.
|
|
||||||
|
|
||||||
|
|
||||||
## Structure Definition
|
|
||||||
|
|
||||||
The `device_operations` structure, defined in
|
|
||||||
`src/include/device/device.h`, consists of several function pointers,
|
|
||||||
each representing a specific operation performed on a device during
|
|
||||||
boot:
|
|
||||||
|
|
||||||
```c
|
|
||||||
struct device_operations {
|
|
||||||
void (*read_resources)(struct device *dev);
|
|
||||||
void (*set_resources)(struct device *dev);
|
|
||||||
void (*enable_resources)(struct device *dev);
|
|
||||||
void (*init)(struct device *dev);
|
|
||||||
void (*final)(struct device *dev);
|
|
||||||
void (*scan_bus)(struct device *bus);
|
|
||||||
void (*enable)(struct device *dev);
|
|
||||||
void (*vga_disable)(struct device *dev);
|
|
||||||
void (*reset_bus)(struct bus *bus);
|
|
||||||
|
|
||||||
int (*get_smbios_data)(struct device *dev, int *handle,
|
|
||||||
unsigned long *current);
|
|
||||||
void (*get_smbios_strings)(struct device *dev, struct smbios_type11 *t);
|
|
||||||
|
|
||||||
unsigned long (*write_acpi_tables)(const struct device *dev,
|
|
||||||
unsigned long start, struct acpi_rsdp *rsdp);
|
|
||||||
void (*acpi_fill_ssdt)(const struct device *dev);
|
|
||||||
const char *(*acpi_name)(const struct device *dev);
|
|
||||||
const char *(*acpi_hid)(const struct device *dev);
|
|
||||||
|
|
||||||
const struct pci_operations *ops_pci;
|
|
||||||
const struct i2c_bus_operations *ops_i2c_bus;
|
|
||||||
const struct spi_bus_operations *ops_spi_bus;
|
|
||||||
const struct smbus_bus_operations *ops_smbus_bus;
|
|
||||||
const struct pnp_mode_ops *ops_pnp_mode;
|
|
||||||
const struct gpio_operations *ops_gpio;
|
|
||||||
const struct mdio_bus_operations *ops_mdio;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Core Resource Management Functions
|
|
||||||
|
|
||||||
* `read_resources`: Discovers and collects resources required by the
|
|
||||||
device (I/O ports, memory regions, IRQs, etc.). This typically
|
|
||||||
involves reading configuration registers or static device tree
|
|
||||||
information.
|
|
||||||
* `set_resources`: Assigns finalized resources to the device after the
|
|
||||||
resource allocation phase. This writes the assigned base addresses,
|
|
||||||
lengths, and other parameters back to the device structure, but not
|
|
||||||
necessarily to hardware registers yet.
|
|
||||||
* `enable_resources`: Activates the assigned resources in the device's
|
|
||||||
hardware registers (e.g., writing to PCI BARs, enabling memory
|
|
||||||
decoding).
|
|
||||||
|
|
||||||
|
|
||||||
### Device Lifecycle Functions
|
|
||||||
|
|
||||||
* `init`: Performs device-specific initialization, often requiring
|
|
||||||
access to the device's assigned resources. This is called after
|
|
||||||
resources have been enabled.
|
|
||||||
* `final`: Executes final setup or cleanup operations before the
|
|
||||||
payload is loaded. This is useful for tasks that depend on other
|
|
||||||
devices being initialized.
|
|
||||||
* `enable`: Enables the device in the hardware, often setting bits in
|
|
||||||
configuration registers to make the device active. Called after
|
|
||||||
`enable_resources`.
|
|
||||||
|
|
||||||
|
|
||||||
### Bus Management Functions
|
|
||||||
|
|
||||||
* `scan_bus`: Enumerates child devices on a bus device (e.g., scanning
|
|
||||||
a PCI bus for devices, probing I2C devices). Only applicable to
|
|
||||||
devices that act as buses.
|
|
||||||
* `reset_bus`: Resets all devices on a specific bus.
|
|
||||||
* `vga_disable`: Disables VGA decoding on a PCI device when another VGA
|
|
||||||
device is active. Used to manage legacy VGA resources.
|
|
||||||
|
|
||||||
|
|
||||||
### System Table Generation Functions
|
|
||||||
|
|
||||||
* `get_smbios_data`: Provides SMBIOS data specific to the device for
|
|
||||||
Type 9 (System Slots) or Type 41 (Onboard Devices Extended
|
|
||||||
Information).
|
|
||||||
* `get_smbios_strings`: Supplies string information for SMBIOS tables,
|
|
||||||
often related to the data provided by `get_smbios_data`.
|
|
||||||
* `write_acpi_tables`: Generates device-specific ACPI tables (like SSDTs)
|
|
||||||
or contributes data to system-wide tables.
|
|
||||||
* `acpi_fill_ssdt`: Adds device-specific objects (scopes, methods, data)
|
|
||||||
to the Secondary System Description Table (SSDT).
|
|
||||||
* `acpi_name`: Returns the ACPI name for the device (e.g.,
|
|
||||||
`\_SB.PCI0.GFX0`). This defines the device's path in the ACPI
|
|
||||||
namespace.
|
|
||||||
* `acpi_hid`: Returns the ACPI Hardware ID (HID) for the device (e.g.,
|
|
||||||
`PNP0A08`). Used by the OS to match drivers.
|
|
||||||
|
|
||||||
|
|
||||||
### Bus-Specific Operation Pointers
|
|
||||||
|
|
||||||
These fields point to bus-specific operation structures when a device
|
|
||||||
functions as a bus controller (or exposes bus-like functionality). See
|
|
||||||
the "Bus-Specific Operations" section for details.
|
|
||||||
|
|
||||||
* `ops_pci`: Operations for PCI configuration space access.
|
|
||||||
* `ops_i2c_bus`: Operations for I2C bus transactions (read, write,
|
|
||||||
transfer).
|
|
||||||
* `ops_spi_bus`: Operations for SPI bus transactions.
|
|
||||||
* `ops_smbus_bus`: Operations for SMBus transactions.
|
|
||||||
* `ops_pnp_mode`: Operations for Plug-and-Play device configuration.
|
|
||||||
* `ops_gpio`: Operations for GPIO control (get, set, configure
|
|
||||||
direction/pulls).
|
|
||||||
* `ops_mdio`: Operations for MDIO (Management Data Input/Output) bus
|
|
||||||
access, used for Ethernet PHYs.
|
|
||||||
|
|
||||||
|
|
||||||
## Device Lifecycle in coreboot
|
|
||||||
|
|
||||||
The function pointers in `device_operations` are called at specific
|
|
||||||
stages during the boot process, following a sequence defined in
|
|
||||||
coreboot's boot state machine (`src/lib/hardwaremain.c`). Understanding
|
|
||||||
this lifecycle helps developers implement appropriate behavior for each
|
|
||||||
function pointer.
|
|
||||||
|
|
||||||
|
|
||||||
### Boot Sequence and Device Operations
|
|
||||||
|
|
||||||
coreboot's main device initialization sequence involves these boot
|
|
||||||
states:
|
|
||||||
|
|
||||||
1. **BS_DEV_INIT_CHIPS** (`dev_initialize_chips()`): Initializes chip
|
|
||||||
drivers (`chip_operations`).
|
|
||||||
2. **BS_DEV_ENUMERATE** (`dev_enumerate()`): Discovers and enumerates
|
|
||||||
devices.
|
|
||||||
* Calls `scan_bus()` for each bus to detect child devices.
|
|
||||||
3. **BS_DEV_RESOURCES** (`dev_configure()`): Allocates resources across
|
|
||||||
all enumerated devices.
|
|
||||||
* Calls `read_resources()` for each device to discover required
|
|
||||||
resources.
|
|
||||||
* Calls `set_resources()` for each device to assign allocated
|
|
||||||
resources back to the `struct device`.
|
|
||||||
4. **BS_DEV_ENABLE** (`dev_enable()`): Enables devices and their
|
|
||||||
resources.
|
|
||||||
* Calls `enable_resources()` for each device to activate assigned
|
|
||||||
resources in hardware.
|
|
||||||
* Calls `enable()` for each device to perform general hardware
|
|
||||||
enablement.
|
|
||||||
5. **BS_DEV_INIT** (`dev_initialize()`): Initializes devices.
|
|
||||||
* Calls `init()` for each device to perform device-specific setup.
|
|
||||||
6. **BS_POST_DEVICE** (`dev_finalize()`): Finalizes devices before
|
|
||||||
payload loading.
|
|
||||||
* Calls `final()` for each device for any final cleanup or setup.
|
|
||||||
|
|
||||||
The sequence is primarily driven by the `boot_states` array in
|
|
||||||
`src/lib/hardwaremain.c`:
|
|
||||||
|
|
||||||
```c
|
|
||||||
static struct boot_state boot_states[] = {
|
|
||||||
/* ... other states ... */
|
|
||||||
BS_INIT_ENTRY(BS_PRE_DEVICE, bs_pre_device),
|
|
||||||
BS_INIT_ENTRY(BS_DEV_INIT_CHIPS, bs_dev_init_chips),
|
|
||||||
BS_INIT_ENTRY(BS_DEV_ENUMERATE, bs_dev_enumerate),
|
|
||||||
BS_INIT_ENTRY(BS_DEV_RESOURCES, bs_dev_resources),
|
|
||||||
BS_INIT_ENTRY(BS_DEV_ENABLE, bs_dev_enable),
|
|
||||||
BS_INIT_ENTRY(BS_DEV_INIT, bs_dev_init),
|
|
||||||
BS_INIT_ENTRY(BS_POST_DEVICE, bs_post_device),
|
|
||||||
/* ... other states ... */
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Later stages include ACPI and SMBIOS table generation, where functions
|
|
||||||
like `write_acpi_tables()`, `acpi_fill_ssdt()`, `get_smbios_data()`, and
|
|
||||||
`get_smbios_strings()` are invoked as part of the table construction
|
|
||||||
process.
|
|
||||||
|
|
||||||
|
|
||||||
## Inheritance and Code Reuse Patterns
|
|
||||||
|
|
||||||
The `device_operations` structure enables several patterns for code
|
|
||||||
reuse:
|
|
||||||
|
|
||||||
|
|
||||||
### 1. Default Implementations
|
|
||||||
|
|
||||||
coreboot provides default implementations for common device types (like
|
|
||||||
root devices, PCI devices, PCI bridges), which can be used directly or
|
|
||||||
extended. Chip or mainboard code often assigns these defaults if no
|
|
||||||
specific driver is found.
|
|
||||||
|
|
||||||
```c
|
|
||||||
/* From src/device/root_device.c */
|
|
||||||
struct device_operations default_dev_ops_root = {
|
|
||||||
.read_resources = noop_read_resources,
|
|
||||||
.set_resources = noop_set_resources,
|
|
||||||
.scan_bus = scan_static_bus,
|
|
||||||
.reset_bus = root_dev_reset,
|
|
||||||
#if CONFIG(HAVE_ACPI_TABLES)
|
|
||||||
.acpi_name = root_dev_acpi_name,
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### 2. No-op Functions
|
|
||||||
|
|
||||||
Simple shim functions (often static inline) are provided for cases where
|
|
||||||
a device doesn't need to implement specific operations. Using these avoids
|
|
||||||
leaving function pointers NULL.
|
|
||||||
|
|
||||||
```c
|
|
||||||
/* From src/include/device/device.h */
|
|
||||||
static inline void noop_read_resources(struct device *dev) {}
|
|
||||||
static inline void noop_set_resources(struct device *dev) {}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### 3. Chain of Responsibility / Delegation
|
|
||||||
|
|
||||||
Some implementations delegate to parent devices or use helper functions
|
|
||||||
when they can't handle an operation themselves or when common logic can
|
|
||||||
be shared. For example, ACPI name generation often traverses up the
|
|
||||||
device tree.
|
|
||||||
|
|
||||||
```c
|
|
||||||
/* Simplified example logic */
|
|
||||||
const char *acpi_device_name(const struct device *dev)
|
|
||||||
{
|
|
||||||
const char *name = NULL;
|
|
||||||
const struct device *pdev = dev;
|
|
||||||
|
|
||||||
/* Check for device specific handler */
|
|
||||||
if (dev->ops && dev->ops->acpi_name) {
|
|
||||||
name = dev->ops->acpi_name(dev);
|
|
||||||
if (name)
|
|
||||||
return name; /* Device handled it */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Walk up the tree to find if any parent can provide a name */
|
|
||||||
while (pdev->upstream && pdev->upstream->dev) {
|
|
||||||
pdev = pdev->upstream->dev;
|
|
||||||
if (pdev->ops && pdev->ops->acpi_name) {
|
|
||||||
/* Note: Parent's acpi_name might handle the original child 'dev' */
|
|
||||||
name = pdev->ops->acpi_name(dev);
|
|
||||||
if (name)
|
|
||||||
return name; /* Parent handled it */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fallback or default logic if needed */
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
This pattern allows parent devices (like buses) to provide default
|
|
||||||
behavior or naming schemes if a child device doesn't specify its own.
|
|
||||||
|
|
||||||
|
|
||||||
## Implementation Examples
|
|
||||||
|
|
||||||
These examples show typical `device_operations` assignments. Actual
|
|
||||||
implementations might involve more conditional compilation based on
|
|
||||||
Kconfig options.
|
|
||||||
|
|
||||||
|
|
||||||
### PCI Device Operations (Default)
|
|
||||||
|
|
||||||
```c
|
|
||||||
/* From src/device/pci_device.c */
|
|
||||||
struct device_operations default_pci_ops_dev = {
|
|
||||||
.read_resources = pci_dev_read_resources,
|
|
||||||
.set_resources = pci_dev_set_resources,
|
|
||||||
.enable_resources = pci_dev_enable_resources,
|
|
||||||
#if CONFIG(HAVE_ACPI_TABLES)
|
|
||||||
.write_acpi_tables = pci_rom_write_acpi_tables,
|
|
||||||
.acpi_fill_ssdt = pci_rom_ssdt,
|
|
||||||
#endif
|
|
||||||
.init = pci_dev_init,
|
|
||||||
/* Assigns PCI-specific operations */
|
|
||||||
.ops_pci = &pci_dev_ops_pci,
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### CPU Cluster Operations
|
|
||||||
|
|
||||||
```c
|
|
||||||
/* From src/soc/intel/alderlake/chip.c (representative example) */
|
|
||||||
static struct device_operations cpu_bus_ops = {
|
|
||||||
.read_resources = noop_read_resources,
|
|
||||||
.set_resources = noop_set_resources,
|
|
||||||
.enable_resources = cpu_set_north_irqs,
|
|
||||||
#if CONFIG(HAVE_ACPI_TABLES)
|
|
||||||
.acpi_fill_ssdt = cpu_fill_ssdt,
|
|
||||||
#endif
|
|
||||||
/* CPU clusters often don't need scan_bus, init, etc. */
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### GPIO Controller Operations
|
|
||||||
|
|
||||||
```c
|
|
||||||
/* From src/soc/intel/common/block/gpio/gpio_dev.c */
|
|
||||||
static struct gpio_operations gpio_ops = {
|
|
||||||
.get = gpio_get,
|
|
||||||
.set = gpio_set,
|
|
||||||
/* ... other GPIO functions ... */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct device_operations block_gpio_ops = {
|
|
||||||
.read_resources = noop_read_resources,
|
|
||||||
.set_resources = noop_set_resources,
|
|
||||||
/* Assigns GPIO-specific operations */
|
|
||||||
.ops_gpio = &gpio_ops,
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Registration and Discovery
|
|
||||||
|
|
||||||
How are `device_operations` structures associated with `struct device`
|
|
||||||
instances?
|
|
||||||
|
|
||||||
|
|
||||||
### 1. Static Assignment (via `chip_operations`)
|
|
||||||
|
|
||||||
For devices known at build time (defined in devicetree.cb), the
|
|
||||||
`device_operations` structure is often assigned in the SOC's or
|
|
||||||
mainboard's `chip_operations->enable_dev()` function based on the
|
|
||||||
device path type or other properties.
|
|
||||||
|
|
||||||
```c
|
|
||||||
/* Example from src/soc/intel/alderlake/chip.c */
|
|
||||||
static void soc_enable(struct device *dev)
|
|
||||||
{
|
|
||||||
/* Assign ops based on the device's role in the tree */
|
|
||||||
if (dev->path.type == DEVICE_PATH_DOMAIN)
|
|
||||||
dev->ops = &pci_domain_ops; /* Handles PCI domain resources */
|
|
||||||
else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER)
|
|
||||||
dev->ops = &cpu_bus_ops; /* Handles CPU cluster setup */
|
|
||||||
else if (dev->path.type == DEVICE_PATH_GPIO)
|
|
||||||
block_gpio_enable(dev); /* Assigns block_gpio_ops */
|
|
||||||
/* ... other assignments for specific PCI devices, etc. ... */
|
|
||||||
}
|
|
||||||
```
|
|
||||||
The `enable_dev` function is part of `struct chip_operations`, which
|
|
||||||
handles broader chip-level initialization (see "Relationship with
|
|
||||||
`chip_operations`" section).
|
|
||||||
|
|
||||||
|
|
||||||
### 2. Dynamic Detection (PCI Drivers)
|
|
||||||
|
|
||||||
For PCI devices discovered during bus scanning (`scan_bus`), coreboot
|
|
||||||
looks through a list of registered PCI drivers (`_pci_drivers` array)
|
|
||||||
to find one matching the device's vendor and device IDs.
|
|
||||||
|
|
||||||
```c
|
|
||||||
/* Logic from src/device/pci_device.c::set_pci_ops() */
|
|
||||||
static void set_pci_ops(struct device *dev)
|
|
||||||
{
|
|
||||||
struct pci_driver *driver;
|
|
||||||
|
|
||||||
/* Check if ops already assigned (e.g., by chip_ops->enable_dev) */
|
|
||||||
if (dev->ops)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Look through registered PCI drivers */
|
|
||||||
for (driver = &_pci_drivers[0]; driver != &_epci_drivers[0]; driver++) {
|
|
||||||
if ((driver->vendor == dev->vendor) &&
|
|
||||||
device_id_match(driver, dev->device)) {
|
|
||||||
/* Found a matching driver, assign its ops */
|
|
||||||
dev->ops = (struct device_operations *)driver->ops;
|
|
||||||
printk(BIOS_SPEW, "%s: Assigned ops from driver for %04x:%04x\n",
|
|
||||||
dev_path(dev), driver->vendor, driver->device);
|
|
||||||
return; /* Stop searching */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fall back to default operations if no specific driver found */
|
|
||||||
if (!dev->ops) {
|
|
||||||
if ((dev->hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) {
|
|
||||||
dev->ops = get_pci_bridge_ops(dev); /* Special ops for bridges */
|
|
||||||
} else {
|
|
||||||
dev->ops = &default_pci_ops_dev; /* Default for normal devices */
|
|
||||||
}
|
|
||||||
printk(BIOS_SPEW, "%s: Assigned default PCI ops\n", dev_path(dev));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Build Process Integration
|
|
||||||
|
|
||||||
The `device_operations` structures are integrated into the coreboot
|
|
||||||
build process:
|
|
||||||
|
|
||||||
1. **Static Device Tree**: The mainboard's `devicetree.cb` defines the
|
|
||||||
initial device hierarchy. The build process converts this into C
|
|
||||||
code (`static.c`) containing `struct device` instances.
|
|
||||||
2. **PCI Driver Registration**: PCI drivers (containing their own
|
|
||||||
`device_operations`) register themselves using the `__pci_driver`
|
|
||||||
linker set macro.
|
|
||||||
|
|
||||||
```c
|
|
||||||
/* Example pattern */
|
|
||||||
struct pci_driver example_pci_driver __pci_driver = {
|
|
||||||
.ops = &example_device_ops, /* Pointer to device_operations */
|
|
||||||
.vendor = VENDOR_ID,
|
|
||||||
.device = DEVICE_ID, /* Or .devices for a list */
|
|
||||||
};
|
|
||||||
```
|
|
||||||
3. **Linking**: The build system collects all structures placed in the
|
|
||||||
`__pci_driver` section and creates the `_pci_drivers` array used by
|
|
||||||
`set_pci_ops()`. It ensures all necessary code (default ops, driver
|
|
||||||
ops, core device functions) is linked into the final firmware image.
|
|
||||||
|
|
||||||
|
|
||||||
## Relationship with `chip_operations`
|
|
||||||
|
|
||||||
It's important to distinguish `device_operations` from
|
|
||||||
`chip_operations` (defined in `src/include/chip.h`).
|
|
||||||
|
|
||||||
* `chip_operations`: Defines operations related to the overall chipset
|
|
||||||
or mainboard logic. It includes functions called earlier in the boot
|
|
||||||
process, like `enable_dev`, `init`, and `final`.
|
|
||||||
* `chip_operations->enable_dev()` is crucial as it often performs
|
|
||||||
initial setup for static devices and is the primary place where
|
|
||||||
`device_operations` pointers are *assigned* for non-PCI devices
|
|
||||||
based on their path or type.
|
|
||||||
* `chip_operations->init()` runs during `BS_DEV_INIT_CHIPS`, before
|
|
||||||
most `device_operations` functions.
|
|
||||||
* `device_operations`: Defines operations for *individual* devices
|
|
||||||
within the device tree. These are called *after* the corresponding
|
|
||||||
`chip_operations` stage and operate on a specific `struct device`.
|
|
||||||
|
|
||||||
Essentially, `chip_operations` sets the stage at the SoC/mainboard level,
|
|
||||||
including assigning the correct `device_operations` to static devices,
|
|
||||||
while `device_operations` handles the specific actions for each device
|
|
||||||
later in the boot process.
|
|
||||||
|
|
||||||
|
|
||||||
## Bus-Specific Operations
|
|
||||||
|
|
||||||
The `ops_*` pointers within `struct device_operations` (e.g., `ops_pci`,
|
|
||||||
`ops_i2c_bus`, `ops_spi_bus`, `ops_gpio`) provide a way for devices that
|
|
||||||
act as bus controllers or expose bus-like interfaces to offer
|
|
||||||
standardized access methods.
|
|
||||||
|
|
||||||
* **Purpose:** They abstract the low-level details of interacting with
|
|
||||||
that specific bus type. For example, a PCI host bridge device will
|
|
||||||
implement `struct pci_operations` via its `ops_pci` pointer,
|
|
||||||
allowing other code to perform PCI config reads/writes through it
|
|
||||||
without knowing the exact hardware mechanism. Similarly, an I2C
|
|
||||||
controller device implements `struct i2c_bus_operations` via
|
|
||||||
`ops_i2c_bus` to provide standard `read`, `write`, and `transfer`
|
|
||||||
functions for that bus segment.
|
|
||||||
* **Usage:** Code needing to interact with a bus first finds the
|
|
||||||
controller `struct device` in the tree, then accesses the relevant
|
|
||||||
bus operations through the appropriate `ops_*` pointer, passing the
|
|
||||||
target address or parameters. For instance, to talk to an I2C device
|
|
||||||
at address `0x50` on the bus controlled by `i2c_controller_dev`, one
|
|
||||||
might call:
|
|
||||||
`i2c_controller_dev->ops->ops_i2c_bus->transfer(...)`. Helper
|
|
||||||
functions often wrap this access pattern.
|
|
||||||
* **Implementation:** The structures like `struct pci_operations`,
|
|
||||||
`struct i2c_bus_operations`, etc., are defined in corresponding
|
|
||||||
header files (e.g., `src/include/device/pci_ops.h`,
|
|
||||||
`src/include/drivers/i2c/i2c_bus.h`). Devices acting as controllers
|
|
||||||
provide concrete implementations of these functions, tailored to their
|
|
||||||
hardware.
|
|
||||||
|
|
||||||
This mechanism allows coreboot to manage diverse bus types using a
|
|
||||||
consistent device model, where the controller device itself exposes the
|
|
||||||
necessary functions for interacting with devices on its bus.
|
|
||||||
|
|
||||||
|
|
||||||
## Best Practices
|
|
||||||
|
|
||||||
When implementing `device_operations`:
|
|
||||||
|
|
||||||
1. **Leverage Defaults/No-ops**: Use default or no-op implementations
|
|
||||||
whenever possible. Only override functions that require custom
|
|
||||||
behavior for your specific device.
|
|
||||||
2. **Error Handling**: Check return values from functions called within
|
|
||||||
your ops implementations and handle errors gracefully (e.g., log an
|
|
||||||
error, return an error code if applicable).
|
|
||||||
3. **Resource Management**: In `read_resources`, accurately declare all
|
|
||||||
resources (MMIO, I/O ports, IRQs) your device needs, specifying
|
|
||||||
flags like fixed vs. alignment, or bridge vs. standard device.
|
|
||||||
Incorrect resource declaration is a common source of issues.
|
|
||||||
4. **Initialization Order**: Be mindful of dependencies in `init`. If
|
|
||||||
your device relies on another device being fully initialized, consider
|
|
||||||
deferring that part of the initialization to the `final` callback,
|
|
||||||
which runs later.
|
|
||||||
5. **Minimal Implementation**: Only implement the functions relevant to
|
|
||||||
your device type. A simple MMIO device might only need
|
|
||||||
`read_resources`, `set_resources`, `enable_resources`, and perhaps
|
|
||||||
ACPI functions. A bus device additionally needs `scan_bus`.
|
|
||||||
6. **Bus Operations**: If implementing a bus controller, correctly
|
|
||||||
implement the corresponding bus operations structure (e.g.,
|
|
||||||
`struct pci_operations`, `struct i2c_bus_operations`) and assign it
|
|
||||||
to the appropriate `ops_*` field.
|
|
||||||
7. **ACPI/SMBIOS**: If the device needs OS visibility via ACPI or
|
|
||||||
SMBIOS, implement the relevant functions (`acpi_name`, `acpi_hid`,
|
|
||||||
`acpi_fill_ssdt`, `get_smbios_data`, etc.). Ensure ACPI names and
|
|
||||||
HIDs are correct according to specifications and platform needs.
|
|
||||||
|
|
||||||
|
|
||||||
## Logging and Debugging
|
|
||||||
|
|
||||||
Use coreboot's logging facilities (`printk`) within your `device_operations`
|
|
||||||
functions to provide visibility during development and debugging. Use
|
|
||||||
appropriate log levels (e.g., `BIOS_DEBUG`, `BIOS_INFO`, `BIOS_ERR`).
|
|
||||||
|
|
||||||
```c
|
|
||||||
static void example_device_init(struct device *dev)
|
|
||||||
{
|
|
||||||
printk(BIOS_DEBUG, "%s: Initializing device at %s\n", __func__,
|
|
||||||
dev_path(dev));
|
|
||||||
|
|
||||||
/* ... Device initialization code ... */
|
|
||||||
if (/* some condition */) {
|
|
||||||
printk(BIOS_SPEW, "%s: Condition met, applying setting X\n",
|
|
||||||
dev_path(dev));
|
|
||||||
/* ... */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (/* error condition */) {
|
|
||||||
printk(BIOS_ERR, "%s: Failed to initialize feature Y!\n",
|
|
||||||
dev_path(dev));
|
|
||||||
/* Handle error */
|
|
||||||
}
|
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "%s: Initialization complete for %s\n", __func__,
|
|
||||||
dev_path(dev));
|
|
||||||
}
|
|
||||||
```
|
|
||||||
Consistent logging helps trace the boot process and pinpoint where issues
|
|
||||||
occur.
|
|
||||||
|
|
||||||
|
|
||||||
## Common Troubleshooting
|
|
||||||
|
|
||||||
* **Missing Resource Declarations**:
|
|
||||||
* *Problem*: Device fails to function, or conflicts arise because a
|
|
||||||
required resource (MMIO range, I/O port, IRQ) was not declared
|
|
||||||
in `read_resources`. The resource allocator is unaware of the
|
|
||||||
need.
|
|
||||||
* *Solution*: Verify that `read_resources` correctly calls functions
|
|
||||||
like `pci_dev_read_resources` or manually adds all necessary
|
|
||||||
resources using functions like `mmio_resource()`,
|
|
||||||
`io_resource()`, etc. Check PCI BARs or device datasheets.
|
|
||||||
* **Initialization Order Issues**:
|
|
||||||
* *Problem*: `init()` fails because it depends on another device
|
|
||||||
that hasn't been fully initialized yet (e.g., accessing a shared
|
|
||||||
resource like SMBus before the SMBus controller is ready).
|
|
||||||
* *Solution*: Move the dependent initialization code to the `final`
|
|
||||||
callback if possible. Alternatively, ensure the dependency is met
|
|
||||||
by careful ordering in the device tree or using boot state
|
|
||||||
callbacks if necessary for complex scenarios.
|
|
||||||
* **Resource Conflicts**:
|
|
||||||
* *Problem*: Boot fails during resource allocation, or devices
|
|
||||||
misbehave because multiple devices requested the same
|
|
||||||
non-sharable resource (e.g., conflicting fixed MMIO regions).
|
|
||||||
* *Solution*: Review resource declarations in `read_resources` across
|
|
||||||
all relevant devices. Ensure fixed resources don't overlap. Check
|
|
||||||
if bridge windows are correctly defined and large enough. Use
|
|
||||||
coreboot's resource reporting logs to identify overlaps.
|
|
||||||
* **ACPI Table Generation Errors**:
|
|
||||||
* *Problem*: The operating system fails to recognize the device,
|
|
||||||
assigns the wrong driver, or the device doesn't function correctly
|
|
||||||
(e.g., power management issues).
|
|
||||||
* *Solution*: Double-check the `acpi_name`, `acpi_hid`, `_CRS`
|
|
||||||
(generated from assigned resources), and `acpi_fill_ssdt`
|
|
||||||
implementations. Verify names match the ACPI hierarchy and HIDs
|
|
||||||
match expected driver bindings. Ensure SSDT methods correctly
|
|
||||||
access hardware. Use OS debugging tools (e.g., `acpidump`, Device
|
|
||||||
Manager errors) to diagnose.
|
|
||||||
* **Incorrect `ops` Pointer Assigned**:
|
|
||||||
* *Problem*: Device behaves incorrectly because the wrong
|
|
||||||
`device_operations` structure was assigned (e.g., default PCI ops
|
|
||||||
assigned to a device needing a specific driver's ops).
|
|
||||||
* *Solution*: Check the logic in `chip_operations->enable_dev` (for
|
|
||||||
static devices) or the PCI driver registration (`__pci_driver`
|
|
||||||
macro and `set_pci_ops` fallback logic) to ensure the correct
|
|
||||||
`ops` structure is being selected and assigned based on device
|
|
||||||
type, path, or PCI ID. Add debug prints to verify which `ops`
|
|
||||||
structure is assigned.
|
|
||||||
|
|
||||||
|
|
||||||
## Advanced Usage
|
|
||||||
|
|
||||||
### Complex Device Hierarchies
|
|
||||||
|
|
||||||
For devices with non-standard interactions or complex initialization,
|
|
||||||
custom `device_operations` can be created, often inheriting from defaults
|
|
||||||
but overriding specific functions.
|
|
||||||
|
|
||||||
```c
|
|
||||||
static void advanced_device_init(struct device *dev)
|
|
||||||
{
|
|
||||||
/* First, perform standard PCI init */
|
|
||||||
pci_dev_init(dev);
|
|
||||||
|
|
||||||
/* Then, add custom initialization steps */
|
|
||||||
printk(BIOS_DEBUG, "%s: Performing advanced init\n", dev_path(dev));
|
|
||||||
/* ... custom register writes, configuration ... */
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *advanced_device_acpi_name(const struct device *dev)
|
|
||||||
{
|
|
||||||
/* Provide a custom ACPI name based on some property */
|
|
||||||
if (/* condition */)
|
|
||||||
return "ADV0001";
|
|
||||||
else
|
|
||||||
return "ADV0002";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Combine default and custom operations */
|
|
||||||
static struct device_operations advanced_device_ops = {
|
|
||||||
/* Inherit resource handling from default PCI ops */
|
|
||||||
.read_resources = pci_dev_read_resources,
|
|
||||||
.set_resources = pci_dev_set_resources,
|
|
||||||
.enable_resources = pci_dev_enable_resources,
|
|
||||||
|
|
||||||
/* Override init */
|
|
||||||
.init = advanced_device_init,
|
|
||||||
|
|
||||||
/* Override ACPI naming */
|
|
||||||
.acpi_name = advanced_device_acpi_name,
|
|
||||||
/* Other functions might use defaults or no-ops */
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### Dynamic Configuration based on Probing
|
|
||||||
|
|
||||||
Some `init` or other op implementations might probe the device's
|
|
||||||
capabilities or read configuration data (e.g., from SPD, VPD, or straps)
|
|
||||||
and alter their behavior accordingly.
|
|
||||||
|
|
||||||
```c
|
|
||||||
static void conditional_device_init(struct device *dev)
|
|
||||||
{
|
|
||||||
uint8_t feature_flags;
|
|
||||||
|
|
||||||
/* Read capability register from the device */
|
|
||||||
feature_flags = pci_read_config8(dev, EXAMPLE_CAP_REG);
|
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "%s: Feature flags: 0x%02x\n", dev_path(dev),
|
|
||||||
feature_flags);
|
|
||||||
|
|
||||||
/* Conditional initialization based on detected features */
|
|
||||||
if (feature_flags & FEATURE_X_ENABLED) {
|
|
||||||
printk(BIOS_INFO, "%s: Initializing Feature X\n", dev_path(dev));
|
|
||||||
init_feature_x(dev);
|
|
||||||
}
|
|
||||||
if (feature_flags & FEATURE_Y_ENABLED) {
|
|
||||||
printk(BIOS_INFO, "%s: Initializing Feature Y\n", dev_path(dev));
|
|
||||||
init_feature_y(dev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
The `device_operations` structure is a powerful abstraction mechanism in
|
|
||||||
coreboot. It enables consistent handling of diverse hardware while
|
|
||||||
allowing for device-specific behavior. By providing a standard interface
|
|
||||||
for device operations throughout the boot process, it simplifies the
|
|
||||||
codebase, enhances maintainability, and provides the extensibility needed
|
|
||||||
to support new hardware platforms.
|
|
||||||
|
|
||||||
Understanding this structure, its relationship with `chip_operations`,
|
|
||||||
and its role in the boot process is essential for coreboot developers,
|
|
||||||
particularly when adding support for new devices or debugging hardware
|
|
||||||
initialization issues. By following the patterns and best practices
|
|
||||||
outlined here, developers can create robust and reusable device driver
|
|
||||||
implementations that integrate smoothly into the coreboot architecture.
|
|
||||||
|
|
@ -1,684 +0,0 @@
|
||||||
# Devicetree
|
|
||||||
|
|
||||||
## Introduction to the coreboot devicetree
|
|
||||||
|
|
||||||
The first thing that may come to mind when one hears "DeviceTree" is a
|
|
||||||
different sort of description file that is generally passed to the Linux
|
|
||||||
kernel to describe a system's components. Both that devicetree and
|
|
||||||
coreboot's devicetree serve fundamentally the same purpose, but are
|
|
||||||
otherwise unrelated and have completely different syntax. The term
|
|
||||||
devicetree was used long before either version was created, and was
|
|
||||||
initially used in coreboot as a generic term.
|
|
||||||
|
|
||||||
coreboot's devicetree's main use is to define and describe the runtime
|
|
||||||
configuration and settings of the hardware on a board, chip or device
|
|
||||||
level. It defines which of the functions of the chips on the board are
|
|
||||||
enabled, and how they're configured.
|
|
||||||
|
|
||||||
The devicetree file is parsed during the build process by a utility
|
|
||||||
named `sconfig`, which translates the devicetree into a tree of C
|
|
||||||
structures containing the included devices. This code is placed in the
|
|
||||||
file `static.c` and a couple of header files, all under the `build`
|
|
||||||
directory. This file is then built into the binaries for the various
|
|
||||||
coreboot stages and is referred to during the coreboot boot process.
|
|
||||||
|
|
||||||
For the early stages of the coreboot boot process, the data that is
|
|
||||||
generated by `sconfig` is a useful resource, but this structure is the
|
|
||||||
critical architectural glue of ramstage. This structure gets filled in
|
|
||||||
with pointers to every chip's initialization code, allowing ramstage to
|
|
||||||
find and initialize those devices through the `chip_operations`
|
|
||||||
structures.
|
|
||||||
|
|
||||||
|
|
||||||
### History of coreboot's devicetree
|
|
||||||
|
|
||||||
The initial devicetree in coreboot was introduced in 2003 by Ron Minnich
|
|
||||||
as a part of the linuxbios config file, 'config.lb'. At this point both
|
|
||||||
the devicetree and config options were in the same file. In 2009,
|
|
||||||
when Kconfig was added into the coreboot build, devicetree was split
|
|
||||||
out into its own file for each mainboard in a commit with this message:
|
|
||||||
|
|
||||||
```text
|
|
||||||
devicetree.cb
|
|
||||||
|
|
||||||
The devicetree that formerly resided in src/mainboard/*/*/Config.lb.
|
|
||||||
|
|
||||||
Just without the build system crap
|
|
||||||
```
|
|
||||||
|
|
||||||
The devicetree structure was initially mainly used only in ramstage for
|
|
||||||
PCI device enumeration, configuration and resource allocation. It has
|
|
||||||
since expanded for use in the pre-ram stages as a read-only structure.
|
|
||||||
|
|
||||||
The language used in the devicetree has been expanded greatly since it
|
|
||||||
was first introduced as well, adding new features every year or so.
|
|
||||||
|
|
||||||
|
|
||||||
### Devicetree Registers
|
|
||||||
|
|
||||||
In coreboot, the devicetree register setting is one of the two main
|
|
||||||
methods used to configure a board's properties. In this way, devicetree
|
|
||||||
is similar in function to Kconfig. It's more flexible in many ways as
|
|
||||||
it can specify not only single values, but also arrays or structures.
|
|
||||||
It's also even more static than Kconfig because there's no update
|
|
||||||
mechanism for it other than editing the devicetree files.
|
|
||||||
|
|
||||||
Chip-specific configuration values are often set using `register`
|
|
||||||
definitions within a `chip` block, corresponding to a `struct` defined
|
|
||||||
in the chip's `chip.h` file.
|
|
||||||
|
|
||||||
For example, in a `chip drivers/gpio/acpi` block, you might set a GPE:
|
|
||||||
|
|
||||||
```text
|
|
||||||
register "gpe0_sts" = "0x42"
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Adding new static configuration options: Devicetree or Kconfig
|
|
||||||
|
|
||||||
When adding options for a new board or chip, there is frequently a
|
|
||||||
decision that needs to be made about how the option should be added.
|
|
||||||
Using the devicetree or Kconfig are the two typical methods of
|
|
||||||
build-time configuration. Below are some general guidelines on when to
|
|
||||||
use each.
|
|
||||||
|
|
||||||
Kconfig should be used if the option configures the build in a Makefile,
|
|
||||||
or if the option is something that should be user selectable. Kconfig
|
|
||||||
is also preferred if the configuration is a global option and not limited
|
|
||||||
to a single chip. Another thing Kconfig excels at is handling decisions
|
|
||||||
based on other configuration options, which devicetree cannot do.
|
|
||||||
|
|
||||||
Devicetree should obviously be used to define the hardware hierarchy.
|
|
||||||
It's also preferred if the option is only used in C code and is static
|
|
||||||
for a mainboard, or if the option is chip-specific. As mentioned
|
|
||||||
earlier, devicetree registers can also define structures or arrays,
|
|
||||||
which Kconfig cannot.
|
|
||||||
|
|
||||||
Both Kconfig and devicetree can be used in C code for runtime
|
|
||||||
configuration, but there's a significant difference in how they are
|
|
||||||
handled. Because Kconfig generates a `#define` for the choice, the
|
|
||||||
compiler can eliminate code paths not used by the option. Devicetree
|
|
||||||
options, however, are actual runtime selections, and the code for all
|
|
||||||
choices remains in the final build.
|
|
||||||
|
|
||||||
|
|
||||||
## Basic Devicetree Syntax
|
|
||||||
|
|
||||||
The coreboot devicetree uses a custom language parsed by the `sconfig`
|
|
||||||
utility. Here's a brief overview of the main keywords and concepts:
|
|
||||||
|
|
||||||
* **`chip <directory>`**: Defines a collection of devices associated
|
|
||||||
with the code in the specified directory. `sconfig` may also parse a
|
|
||||||
`chip.h` file within this directory for register definitions.
|
|
||||||
* **`device <type> <id> [on|off] [alias <name>] ... end`**: Defines a
|
|
||||||
specific hardware device.
|
|
||||||
* `<type>`: Specifies the device type (e.g., `pci`, `cpu_cluster`,
|
|
||||||
`i2c`).
|
|
||||||
* `<id>`: A unique identifier for the device within its type/bus
|
|
||||||
(e.g., PCI BDF `17.0`, I2C address `0x50`).
|
|
||||||
* `on`/`off`: Enables or disables the device definition.
|
|
||||||
* `alias <name>`: Assigns a human-readable alias for referencing
|
|
||||||
this device elsewhere (often used in `chipset.cb`).
|
|
||||||
* `end`: Marks the end of the device definition block. Registers
|
|
||||||
and other properties are defined between `device` and `end`.
|
|
||||||
* **`register "<name>" = <value>`**: Sets the value of a configuration
|
|
||||||
register defined in the corresponding `chip.h` structure. The value
|
|
||||||
can be a number, string, or complex structure initialization.
|
|
||||||
* **`probe <field> <option>`**: Used for firmware configuration
|
|
||||||
(`fw_config`), indicating a setting should be probed at runtime.
|
|
||||||
* **`ops "<identifier>"`**: Associates a `chip_operations` structure
|
|
||||||
with the device, used primarily in ramstage for device initialization.
|
|
||||||
* **`fw_config field <name> size <bits> ... end`**: Defines a firmware
|
|
||||||
configuration field, often used for passing board-specific data to
|
|
||||||
payloads. Options within the field are defined using `option`.
|
|
||||||
* **`ref <alias>`**: Used within `device` definitions in `devicetree.cb`
|
|
||||||
or `overridetree.cb` to refer to a device defined (usually via an
|
|
||||||
`alias`) in a lower-level file like `chipset.cb`.
|
|
||||||
* **`# <comment text>`**: Single-line comments.
|
|
||||||
|
|
||||||
Device definitions can be nested within `chip` blocks. `end` keywords
|
|
||||||
close the current block (`device` or `chip`).
|
|
||||||
|
|
||||||
|
|
||||||
## Three levels of devicetree files
|
|
||||||
|
|
||||||
There are currently three different levels of devicetrees used to build
|
|
||||||
up the structure of components and register values in coreboot. From
|
|
||||||
the lowest, most general level to the highest and most specific, they
|
|
||||||
are `chipset.cb`, `devicetree.cb`, and `overridetree.cb`.
|
|
||||||
|
|
||||||
Unless there's a specific reason to name them something other than these
|
|
||||||
names, they should be used.
|
|
||||||
|
|
||||||
For newer SoCs and chipsets, there will generally be a `chipset.cb` file.
|
|
||||||
Every mainboard requires a `devicetree.cb` file, although it can be empty
|
|
||||||
if everything is inherited from the `chipset.cb`. An `overridetree.cb`
|
|
||||||
file is only required if variants have differences from the primary
|
|
||||||
mainboard's `devicetree.cb`.
|
|
||||||
|
|
||||||
|
|
||||||
### SoC / chipset level, `chipset.cb`
|
|
||||||
|
|
||||||
The `chipset.cb` file was added in October 2020, allowing a single
|
|
||||||
chipset or SoC to provide a "base level" devicetree, reducing
|
|
||||||
duplication between mainboards.
|
|
||||||
|
|
||||||
The `chipset.cb` file also typically defines human-readable "aliases"
|
|
||||||
for particular devices so that mainboards can use those instead of PCI
|
|
||||||
device/function numbers or other hardware identifiers.
|
|
||||||
|
|
||||||
The use of the `chipset.cb` file is specified in Kconfig by the
|
|
||||||
`CHIPSET_DEVICETREE` symbol, which provides the path to the file.
|
|
||||||
|
|
||||||
In a `chipset.cb` file, you might see lines like this:
|
|
||||||
|
|
||||||
```text
|
|
||||||
# Chip definition for the SoC/chipset itself
|
|
||||||
chip soc/intel/common/block
|
|
||||||
|
|
||||||
# Define PCI device 17.0, alias it to "sata", and default it off
|
|
||||||
device pci 17.0 alias sata off end
|
|
||||||
|
|
||||||
# Define PCI device 1e.0, alias it to "uart0", and default it off
|
|
||||||
device pci 1e.0 alias uart0 off end
|
|
||||||
|
|
||||||
end # chip soc/intel/common/block
|
|
||||||
```
|
|
||||||
|
|
||||||
This defines the devices, assigns aliases, and sets their default state.
|
|
||||||
|
|
||||||
|
|
||||||
### Primary mainboard level, `devicetree.cb`
|
|
||||||
|
|
||||||
Each mainboard must have a `devicetree.cb` file. The filename and path are
|
|
||||||
typically set by the `DEVICETREE` Kconfig symbol, defaulting to
|
|
||||||
`src/mainboard/<VENDOR>/<BOARD>/devicetree.cb`.
|
|
||||||
|
|
||||||
If a mainboard using the above `chipset.cb` wanted both devices enabled,
|
|
||||||
its `devicetree.cb` might contain:
|
|
||||||
|
|
||||||
```text
|
|
||||||
# Reference the SATA device by its alias and enable it
|
|
||||||
device ref sata on end
|
|
||||||
|
|
||||||
# Reference the UART0 device by its alias and enable it
|
|
||||||
device ref uart0 on end
|
|
||||||
```
|
|
||||||
|
|
||||||
The `ref` keyword looks up the device (usually by alias) defined in a
|
|
||||||
lower-level file (`chipset.cb` in this case) and modifies its properties.
|
|
||||||
|
|
||||||
|
|
||||||
### Mainboard variant level, `overridetree.cb`
|
|
||||||
|
|
||||||
Introduced in 2018 to reduce duplication and maintenance for board
|
|
||||||
variants, the `overridetree.cb` file is the most specific level.
|
|
||||||
|
|
||||||
This allows a base `devicetree.cb` at the top mainboard level shared by
|
|
||||||
all variants. Each variant then only needs an `overridetree.cb` to
|
|
||||||
specify its differences.
|
|
||||||
|
|
||||||
The override tree filename is set in Kconfig with the
|
|
||||||
`OVERRIDE_DEVICETREE` symbol and is typically named `overridetree.cb`.
|
|
||||||
|
|
||||||
Finally, if one variant of the mainboard lacked a SATA connector, it
|
|
||||||
could disable the SATA device again using the following in its specific
|
|
||||||
`overridetree.cb`:
|
|
||||||
|
|
||||||
```text
|
|
||||||
# Reference the SATA device by alias and disable it for this variant
|
|
||||||
device ref sata off end
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Additional files
|
|
||||||
|
|
||||||
|
|
||||||
### `chip.h` files
|
|
||||||
|
|
||||||
coreboot looks at a "chip" as a collection of devices. This collection
|
|
||||||
can be a single logical device or multiple different ones. The `chip`
|
|
||||||
keyword starts this collection. Following the `chip` keyword is a
|
|
||||||
directory path (relative to `src/`) containing the code for that chip
|
|
||||||
or logical block of hardware.
|
|
||||||
|
|
||||||
There may optionally be a `chip.h` file in that directory. If present,
|
|
||||||
`sconfig` parses this file to define a C structure containing the
|
|
||||||
"register definitions" for the chip. The values for this structure's
|
|
||||||
members are set using the `register` keyword in one of the devicetree
|
|
||||||
files (`chipset.cb`, `devicetree.cb`, `overridetree.cb`). If not
|
|
||||||
explicitly set, members typically default to 0 or follow standard C
|
|
||||||
initialization rules. The `chip.h` file frequently also contains C
|
|
||||||
macros, enums, and sub-structures used for setting the members of the
|
|
||||||
main register structure.
|
|
||||||
|
|
||||||
The C structure for the chip's register definition is named after the
|
|
||||||
directory containing the `chip.h` file, with slashes (`/`) changed to
|
|
||||||
underscores (`_`), and `_config` appended. The leading `src/` is omitted.
|
|
||||||
|
|
||||||
This means that a line in a devicetree file like:
|
|
||||||
`chip drivers/i2c/hid`
|
|
||||||
would cause `sconfig` to look for `src/drivers/i2c/hid/chip.h`. If found,
|
|
||||||
the register definition structure it contains would be named
|
|
||||||
`drivers_i2c_hid_config`.
|
|
||||||
|
|
||||||
Here is the content of `src/drivers/i2c/hid/chip.h`:
|
|
||||||
|
|
||||||
```c
|
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
||||||
|
|
||||||
#ifndef __DRIVERS_I2C_HID_CHIP_H__
|
|
||||||
#define __DRIVERS_I2C_HID_CHIP_H__
|
|
||||||
#include <drivers/i2c/generic/chip.h>
|
|
||||||
#define I2C_HID_CID "PNP0C50"
|
|
||||||
|
|
||||||
struct drivers_i2c_hid_config {
|
|
||||||
struct drivers_i2c_generic_config generic;
|
|
||||||
uint8_t hid_desc_reg_offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __I2C_HID_CHIP_H__ */
|
|
||||||
```
|
|
||||||
|
|
||||||
In a devicetree, you could set `hid_desc_reg_offset` like this:
|
|
||||||
|
|
||||||
```text
|
|
||||||
chip drivers/i2c/hid
|
|
||||||
device i2c 0x2c on
|
|
||||||
# Set the HID descriptor register offset
|
|
||||||
register "hid_desc_reg_offset" = "0x01"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## The `sconfig` utility and generated files
|
|
||||||
|
|
||||||
|
|
||||||
### `util/sconfig`
|
|
||||||
|
|
||||||
`sconfig` is the tool that parses the coreboot devicetrees and turns
|
|
||||||
them into a collection of C structures. This is a coreboot-specific
|
|
||||||
tool, built using flex & bison to define and parse the domain-specific
|
|
||||||
language used by coreboot's devicetree.
|
|
||||||
|
|
||||||
`sconfig` is called by the makefiles during the build process and doesn't
|
|
||||||
generally need to be run directly. If run manually (e.g.,
|
|
||||||
`build/util/sconfig/sconfig --help`), it shows its command-line options.
|
|
||||||
The exact options might vary slightly, but typically include:
|
|
||||||
|
|
||||||
```text
|
|
||||||
usage: sconfig <options>
|
|
||||||
|
|
||||||
-c | --output_c : Path to output static.c file (required)
|
|
||||||
-r | --output_h : Path to header static.h file (required)
|
|
||||||
-d | --output_d : Path to header static_devices.h file (required)
|
|
||||||
-f | --output_f : Path to header static_fw_config.h file (required)
|
|
||||||
-m | --mainboard_devtree : Path to mainboard devicetree file (required)
|
|
||||||
-o | --override_devtree : Path to override devicetree file (optional)
|
|
||||||
-p | --chipset_devtree : Path to chipset/SOC devicetree file (optional)
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### `sconfig` inputs
|
|
||||||
|
|
||||||
The `sconfig` input files `chip.h`, `chipset.cb`, `devicetree.cb`, and
|
|
||||||
`overridetree.cb` were discussed previously. As the usage above shows,
|
|
||||||
the only required input file is the mainboard devicetree (`-m`). The
|
|
||||||
additional devicetree files, `chipset.cb` (`-p`) and `overridetree.cb`
|
|
||||||
(`-o`), are optional. The `chip.h` files do not need to be specified on
|
|
||||||
the command line; their locations are determined by the `chip` directory
|
|
||||||
paths within the `.cb` files.
|
|
||||||
|
|
||||||
Constructing the devicetree input files will be discussed later.
|
|
||||||
|
|
||||||
|
|
||||||
### `sconfig` outputs
|
|
||||||
|
|
||||||
#### `static.c`
|
|
||||||
|
|
||||||
This is the primary C file generated by `sconfig`. It contains the static
|
|
||||||
definitions of the device tree structures, including device nodes, bus
|
|
||||||
links, and register configuration data.
|
|
||||||
|
|
||||||
For historic reasons, `static.c` is generated in the
|
|
||||||
`build/mainboard/<VENDOR>/<BOARD>` directory.
|
|
||||||
|
|
||||||
|
|
||||||
#### `static.h`
|
|
||||||
|
|
||||||
The `static.h` file is the main header file included by most coreboot C
|
|
||||||
files that need access to the devicetree data. It is included by
|
|
||||||
`src/include/device/device.h`, which provides the primary API
|
|
||||||
(definitions, structures, function prototypes) for interacting with the
|
|
||||||
devicetree-generated output.
|
|
||||||
|
|
||||||
`static.h` used to contain all generated declarations directly. As of
|
|
||||||
October 2020, it simply includes the other two generated header files
|
|
||||||
(`static_devices.h` and `static_fw_config.h`). This separation allows
|
|
||||||
the firmware config options (`fw_config`) to be used independently, for
|
|
||||||
example, by a payload.
|
|
||||||
|
|
||||||
|
|
||||||
#### `static_devices.h`
|
|
||||||
|
|
||||||
The file `static_devices.h` contains `extern` declarations for all the
|
|
||||||
device structures (`struct device`) defined in `static.c`. This allows
|
|
||||||
other C files to reference the generated device tree nodes.
|
|
||||||
|
|
||||||
|
|
||||||
#### `static_fw_config.h`
|
|
||||||
|
|
||||||
`static_fw_config.h` contains only the `FW_CONFIG_FIELD_*` macro results,
|
|
||||||
derived from `fw_config` entries in the devicetree. This makes it easily
|
|
||||||
consumable by payloads or other components needing platform `FW_CONFIG`
|
|
||||||
data without pulling in the full device tree structure.
|
|
||||||
|
|
||||||
|
|
||||||
## Devicetree Example
|
|
||||||
|
|
||||||
|
|
||||||
### A very simple devicetree
|
|
||||||
|
|
||||||
This is the `devicetree.cb` file from
|
|
||||||
`src/mainboard/sifive/hifive-unleashed`, with line numbers added for
|
|
||||||
reference. Non-x86 devicetree files are often simpler than their x86
|
|
||||||
counterparts.
|
|
||||||
|
|
||||||
```text
|
|
||||||
1 # SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
2 chip soc/sifive/fu540
|
|
||||||
3 device cpu_cluster 0 on end
|
|
||||||
4 end
|
|
||||||
```
|
|
||||||
|
|
||||||
This can be broken down as follows:
|
|
||||||
|
|
||||||
Line 1: Comments start with `#`. This line is the SPDX license
|
|
||||||
identifier for the file.
|
|
||||||
|
|
||||||
Line 2: `chip soc/sifive/fu540` starts a block for the SiFive FU540 SoC.
|
|
||||||
`sconfig` will look for code and potentially a `chip.h` in
|
|
||||||
`src/soc/sifive/fu540/`.
|
|
||||||
|
|
||||||
Line 3: `device cpu_cluster 0 on end` defines a device of type
|
|
||||||
`cpu_cluster` with ID `0`. It's marked as enabled (`on`). Since there are
|
|
||||||
no registers or other properties defined between `device` and `end`, this
|
|
||||||
is a simple enablement entry.
|
|
||||||
|
|
||||||
Line 4: `end` closes the block started by the `chip` keyword on line 2.
|
|
||||||
|
|
||||||
|
|
||||||
### Generated files
|
|
||||||
|
|
||||||
Continuing with the simple `sifive/hifive-unleashed` mainboard example,
|
|
||||||
these are the files generated by `sconfig` from the devicetree above (as
|
|
||||||
of mid-2022; exact output can change). Because the input devicetree is
|
|
||||||
minimal, the generated files are also quite sparse.
|
|
||||||
|
|
||||||
|
|
||||||
#### `build/static.h`
|
|
||||||
|
|
||||||
```c
|
|
||||||
#ifndef __STATIC_DEVICE_TREE_H
|
|
||||||
#define __STATIC_DEVICE_TREE_H
|
|
||||||
|
|
||||||
#include <static_fw_config.h>
|
|
||||||
#include <static_devices.h>
|
|
||||||
|
|
||||||
#endif /* __STATIC_DEVICE_TREE_H */
|
|
||||||
```
|
|
||||||
(Includes the other generated headers.)
|
|
||||||
|
|
||||||
|
|
||||||
#### `build/static_devices.h`
|
|
||||||
|
|
||||||
```c
|
|
||||||
#ifndef __STATIC_DEVICES_H
|
|
||||||
#define __STATIC_DEVICES_H
|
|
||||||
#include <device/device.h>
|
|
||||||
/* expose_device_names */
|
|
||||||
#endif /* __STATIC_DEVICE_NAMES_H */
|
|
||||||
```
|
|
||||||
(Includes `device/device.h` but contains no actual device externs beyond
|
|
||||||
the implicit root device, as the simple example didn't define complex
|
|
||||||
devices requiring separate structs.)
|
|
||||||
|
|
||||||
|
|
||||||
#### `build/static_fw_config.h`
|
|
||||||
|
|
||||||
```c
|
|
||||||
#ifndef __STATIC_FW_CONFIG_H
|
|
||||||
#define __STATIC_FW_CONFIG_H
|
|
||||||
#endif /* __STATIC_FW_CONFIG_H */
|
|
||||||
```
|
|
||||||
(Empty because the example `devicetree.cb` did not use `fw_config`.)
|
|
||||||
|
|
||||||
|
|
||||||
#### `build/mainboard/sifive/hifive-unleashed/static.c`
|
|
||||||
|
|
||||||
##### Includes
|
|
||||||
|
|
||||||
```text
|
|
||||||
1 #include <boot/coreboot_tables.h>
|
|
||||||
2 #include <device/device.h>
|
|
||||||
3 #include <device/pci.h>
|
|
||||||
4 #include <fw_config.h>
|
|
||||||
5 #include <static.h>
|
|
||||||
```
|
|
||||||
|
|
||||||
Lines 1-5: Includes header files required for the following structure
|
|
||||||
definitions and macros.
|
|
||||||
|
|
||||||
|
|
||||||
##### Declarations for chip-ops
|
|
||||||
|
|
||||||
```text
|
|
||||||
6
|
|
||||||
7 #if !DEVTREE_EARLY
|
|
||||||
8 __attribute__((weak)) struct chip_operations mainboard_ops = {};
|
|
||||||
9 extern struct chip_operations soc_sifive_fu540_ops;
|
|
||||||
10 #endif
|
|
||||||
```
|
|
||||||
|
|
||||||
Lines 7 & 10: The `ops` structures inside this `#if !DEVTREE_EARLY` block
|
|
||||||
are only relevant and linked in ramstage.
|
|
||||||
|
|
||||||
Lines 8-9: Declarations for `chip_operations` structures. This section
|
|
||||||
expands as more chips are added to the devicetree.
|
|
||||||
* Line 8: `mainboard_ops` is always present. It's defined as `weak`
|
|
||||||
because the mainboard C code may or may not provide this structure.
|
|
||||||
* Line 9: This `extern` is generated by the `chip soc/sifive/fu540`
|
|
||||||
declaration in the `devicetree.cb`. There will be a similar line for
|
|
||||||
every `chip` declared.
|
|
||||||
|
|
||||||
##### `STORAGE` definition
|
|
||||||
|
|
||||||
```text
|
|
||||||
11
|
|
||||||
12 #define STORAGE static __unused DEVTREE_CONST
|
|
||||||
```
|
|
||||||
|
|
||||||
Line 12: This macro conditionally adds `const` based on the build stage.
|
|
||||||
It resolves to `static __unused const` in early stages (pre-RAM) and
|
|
||||||
`static __unused` in ramstage, where the structures might be modified.
|
|
||||||
|
|
||||||
##### Structure definitions
|
|
||||||
|
|
||||||
```text
|
|
||||||
13
|
|
||||||
14
|
|
||||||
15 /* pass 0 */
|
|
||||||
16 STORAGE struct bus dev_root_links[];
|
|
||||||
17 STORAGE struct device _dev_0;
|
|
||||||
18 DEVTREE_CONST struct device * DEVTREE_CONST last_dev = &_dev_0;
|
|
||||||
```
|
|
||||||
|
|
||||||
Lines 16-18: Forward declarations of the static structures generated by
|
|
||||||
`sconfig` based on the devicetree input. `_dev_0` corresponds to the
|
|
||||||
`cpu_cluster 0` device.
|
|
||||||
|
|
||||||
##### Register Structures
|
|
||||||
|
|
||||||
```text
|
|
||||||
19
|
|
||||||
20 /* chip configs */
|
|
||||||
```
|
|
||||||
|
|
||||||
Line 20: This section is empty for this mainboard because the
|
|
||||||
`soc/sifive/fu540/chip.h` file (if it exists) does not define a register
|
|
||||||
structure, or the devicetree did not instantiate it using `register`.
|
|
||||||
Otherwise, this section would contain the static initialization of chip
|
|
||||||
configuration structures based on `register` entries.
|
|
||||||
|
|
||||||
##### `dev_root` structure
|
|
||||||
|
|
||||||
Lines 21-44: `dev_root`. This structure represents the root of the
|
|
||||||
coreboot device tree. It is always generated, regardless of the content
|
|
||||||
of the `devicetree.cb` file. It serves as the entry point for traversing
|
|
||||||
the tree.
|
|
||||||
|
|
||||||
```text
|
|
||||||
21
|
|
||||||
22 /* pass 1 */
|
|
||||||
23 DEVTREE_CONST struct device dev_root = {
|
|
||||||
24 #if !DEVTREE_EARLY
|
|
||||||
25 .ops = &default_dev_ops_root,
|
|
||||||
26 #endif
|
|
||||||
27 .bus = &dev_root_links[0],
|
|
||||||
28 .path = { .type = DEVICE_PATH_ROOT },
|
|
||||||
29 .enabled = 1,
|
|
||||||
30 .hidden = 0,
|
|
||||||
31 .mandatory = 0,
|
|
||||||
32 .on_mainboard = 1,
|
|
||||||
33 .link_list = &dev_root_links[0],
|
|
||||||
34 .sibling = NULL,
|
|
||||||
35 #if !DEVTREE_EARLY
|
|
||||||
36 .chip_ops = &mainboard_ops,
|
|
||||||
37 .name = mainboard_name,
|
|
||||||
38 #endif
|
|
||||||
39 .next=&_dev_0,
|
|
||||||
40 #if !DEVTREE_EARLY
|
|
||||||
41 #if CONFIG(GENERATE_SMBIOS_TABLES)
|
|
||||||
42 #endif
|
|
||||||
43 #endif
|
|
||||||
44 };
|
|
||||||
```
|
|
||||||
|
|
||||||
* Lines 24-26: Points to a default ramstage `device_operation`
|
|
||||||
structure (`default_dev_ops_root`) found in
|
|
||||||
`src/device/root_device.c`. This structure typically does little by
|
|
||||||
default but can be overridden or utilized by mainboard code via the
|
|
||||||
`chip_operations->enable_dev()` hook for tasks like ACPI table
|
|
||||||
generation.
|
|
||||||
* Line 27: `.bus`: Pointer to the bus structure associated with this
|
|
||||||
device. For the root device, this points to its own bus structure.
|
|
||||||
* Line 28: `.path`: The unique path identifier for this device. The type
|
|
||||||
is `DEVICE_PATH_ROOT`.
|
|
||||||
* Lines 29-32: Device status flags.
|
|
||||||
* `enabled`: Set based on `on`/`off` in the devicetree (always on
|
|
||||||
for `dev_root`). Can be modified later (e.g., during enumeration
|
|
||||||
in ramstage).
|
|
||||||
* `hidden`, `mandatory`: Set only by corresponding keywords in the
|
|
||||||
devicetree (not used here).
|
|
||||||
* `on_mainboard`: Indicates the device was defined in the static
|
|
||||||
devicetree, as opposed to being discovered dynamically (e.g., via
|
|
||||||
PCI enumeration). Always true for `dev_root`.
|
|
||||||
* Line 33: `.link_list`: Pointer to the list of child buses attached to
|
|
||||||
this device.
|
|
||||||
* Line 34: `.sibling`: Pointer to the next device at the same level in
|
|
||||||
the tree. Should always be `NULL` for `dev_root`.
|
|
||||||
* Line 36: `.chip_ops`: Pointer to the mainboard's `chip_operations`
|
|
||||||
structure (the `weak` `mainboard_ops`). Although not a physical
|
|
||||||
chip, the mainboard gets this to hook into the boot process like
|
|
||||||
other chips.
|
|
||||||
* Line 37: `.name`: A string identifier, typically the mainboard name,
|
|
||||||
set at build time (from `src/device/root_device.c`).
|
|
||||||
* Line 39: `.next`: Pointer used internally by `sconfig` during tree
|
|
||||||
construction. Points to the next device structure processed (`_dev_0`).
|
|
||||||
|
|
||||||
##### `dev_root_links`
|
|
||||||
|
|
||||||
Lines 45-52: The `dev_root` bus structure array.
|
|
||||||
|
|
||||||
This array (`struct bus`) holds pointers defining the bus topology. Each
|
|
||||||
element represents a link on a bus. `dev_root` acts as the bridge for the
|
|
||||||
top-level bus.
|
|
||||||
|
|
||||||
A new bus structure array is typically created for each distinct bus type
|
|
||||||
or domain originating from a bridge device in the devicetree (e.g., PCI
|
|
||||||
domain 0, LPC bus).
|
|
||||||
|
|
||||||
```text
|
|
||||||
45 STORAGE struct bus dev_root_links[] = {
|
|
||||||
46 [0] = {
|
|
||||||
47 .link_num = 0,
|
|
||||||
48 .dev = &dev_root,
|
|
||||||
49 .children = &_dev_0,
|
|
||||||
50 .next = NULL,
|
|
||||||
51 },
|
|
||||||
52 };
|
|
||||||
```
|
|
||||||
|
|
||||||
* Line 47: `.link_num`: Index of this link within the bus array.
|
|
||||||
* Line 48: `.dev`: Pointer back to the bridge device structure for this
|
|
||||||
bus (`dev_root`).
|
|
||||||
* Line 49: `.children`: Pointer to the first child device structure on
|
|
||||||
this bus (`_dev_0`).
|
|
||||||
* Line 50: `.next`: Pointer to the next bridge device on the *parent*
|
|
||||||
bus. Since `dev_root` has no parent bus, this is `NULL`.
|
|
||||||
|
|
||||||
##### `_dev_0`
|
|
||||||
|
|
||||||
Lines 53-72: The `cpu_cluster` device structure (`_dev_0`).
|
|
||||||
|
|
||||||
This structure corresponds directly to the
|
|
||||||
`device cpu_cluster 0 on end` line in the `devicetree.cb`.
|
|
||||||
|
|
||||||
```text
|
|
||||||
53 STORAGE struct device _dev_0 = {
|
|
||||||
54 #if !DEVTREE_EARLY
|
|
||||||
55 .ops = NULL,
|
|
||||||
56 #endif
|
|
||||||
57 .bus = &dev_root_links[0],
|
|
||||||
58 .path = {.type=DEVICE_PATH_CPU_CLUSTER,{.cpu_cluster={ .cluster = 0x0 }}},
|
|
||||||
59 .enabled = 1,
|
|
||||||
60 .hidden = 0,
|
|
||||||
61 .mandatory = 0,
|
|
||||||
62 .on_mainboard = 1,
|
|
||||||
63 .link_list = NULL,
|
|
||||||
64 .sibling = NULL,
|
|
||||||
65 #if !DEVTREE_EARLY
|
|
||||||
66 .chip_ops = &soc_sifive_fu540_ops,
|
|
||||||
67 #endif
|
|
||||||
68 #if !DEVTREE_EARLY
|
|
||||||
69 #if CONFIG(GENERATE_SMBIOS_TABLES)
|
|
||||||
70 #endif
|
|
||||||
71 #endif
|
|
||||||
72 };
|
|
||||||
```
|
|
||||||
|
|
||||||
* Lines 54-56: `.ops`: Pointer to a `device_operations` structure. This
|
|
||||||
is `NULL` because this entry represents the `chip` itself, not a
|
|
||||||
specific functional sub-device requiring device-level operations. The
|
|
||||||
chip-level operations are handled by `chip_ops`.
|
|
||||||
* Line 57: `.bus`: Pointer to the bus structure this device resides on.
|
|
||||||
Since it's directly under `dev_root`, it points to `dev_root_links[0]`.
|
|
||||||
* Line 58: `.path`: The unique device path structure (defined in
|
|
||||||
`src/include/device/path.h`). Type is `DEVICE_PATH_CPU_CLUSTER`,
|
|
||||||
and the cluster ID is `0`, matching the devicetree entry. This path
|
|
||||||
is used when searching the tree (e.g., with `dev_find_path()`).
|
|
||||||
* Lines 59-62: Enumeration Status. Similar to `dev_root`. `enabled = 1`
|
|
||||||
comes from the `on` keyword.
|
|
||||||
* Line 63: `.link_list`: Pointer to child buses. `NULL` because this
|
|
||||||
`cpu_cluster` device doesn't bridge to any further buses in this
|
|
||||||
simple example.
|
|
||||||
* Line 64: `.sibling`: Pointer to the next device at the same level
|
|
||||||
(i.e., another device directly under `dev_root`). `NULL` as it's the
|
|
||||||
only child.
|
|
||||||
* Lines 65-67: `.chip_ops`: Pointer to the processor's `chip_operations`
|
|
||||||
structure (`soc_sifive_fu540_ops`), used in ramstage for SoC/CPU
|
|
||||||
initialization steps. This link comes from the `chip soc/sifive/fu540`
|
|
||||||
declaration.
|
|
||||||
* Lines 68-71: Placeholder for SMBIOS information, enabled by Kconfig.
|
|
||||||
Not used in this example.
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,15 +0,0 @@
|
||||||
# coreboot internals
|
|
||||||
|
|
||||||
This section contains documentation about the configuration and
|
|
||||||
programming APIs internal to coreboot
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
```{toctree}
|
|
||||||
:maxdepth: 1
|
|
||||||
|
|
||||||
coreboot devicetree <devicetree.md>
|
|
||||||
coreboot devicetree language <devicetree_language.md>
|
|
||||||
Chip Operations <chip_operations.md>
|
|
||||||
Device Operations <device_operations>
|
|
||||||
```
|
|
||||||
|
|
@ -2,284 +2,225 @@
|
||||||
|
|
||||||
## Motivation
|
## Motivation
|
||||||
|
|
||||||
The firmware configuration interface in coreboot is designed to support
|
The firmware configuration interface in coreboot is designed to support a wide variety of
|
||||||
a wide variety of configuration options in that are dictated by the
|
configuration options in that are dictated by the hardware at runtime. This allows a single
|
||||||
hardware at runtime. This allows a single BIOS image to be used across a
|
BIOS image to be used across a wide variety of devices which may have key differences but are
|
||||||
wide variety of devices which may have key differences but are otherwise
|
otherwise similar enough to use the same coreboot build target.
|
||||||
similar enough to use the same coreboot build target.
|
|
||||||
|
|
||||||
The initial implementation is designed to take advantage of a bitmask
|
The initial implementation is designed to take advantage of a bitmask returned by the Embedded
|
||||||
returned by the Embedded Controller on Google ChromeOS devices which
|
Controller on Google ChromeOS devices which allows the manufacturer to use the same firmware
|
||||||
allows the manufacturer to use the same firmware image across multiple
|
image across multiple devices by selecting various options at runtime. See the ChromiumOS
|
||||||
devices by selecting various options at runtime. See the ChromiumOS
|
|
||||||
[Firmware Config][1] documentation for more information.
|
[Firmware Config][1] documentation for more information.
|
||||||
|
|
||||||
This firmware configuration interface differs from the CMOS option
|
This firmware configuration interface differs from the CMOS option interface in that this
|
||||||
interface in that this bitmask value is not intended as a
|
bitmask value is not intended as a user-configurable setting as the configuration values must
|
||||||
user-configurable setting as the configuration values must match the
|
match the actual hardware. In the case where a user was to swap their hardware this value
|
||||||
actual hardware. In the case where a user was to swap their hardware
|
would need to be updated or overridden.
|
||||||
this value would need to be updated or overridden.
|
|
||||||
|
|
||||||
|
|
||||||
## Device Presence
|
## Device Presence
|
||||||
|
|
||||||
One common example of why a firmware configuration interface is
|
One common example of why a firmware configuration interface is important is determining if a
|
||||||
important is determining if a device is present in the system. With some
|
device is present in the system. With some bus topologies and hardware mechanisms it is
|
||||||
bus topologies and hardware mechanisms it is possible to probe and
|
possible to probe and enumerate this at runtime:
|
||||||
enumerate this at runtime:
|
|
||||||
|
|
||||||
- PCI is a self-discoverable bus and is very easy to handle.
|
- PCI is a self-discoverable bus and is very easy to handle.
|
||||||
- I2C devices can often be probed with a combination of bus and address.
|
- I2C devices can often be probed with a combination of bus and address.
|
||||||
- The use of GPIOs with external strap to ground or different voltages
|
- The use of GPIOs with external strap to ground or different voltages can be used to detect
|
||||||
can be used to detect presence of a device.
|
presence of a device.
|
||||||
|
|
||||||
However there are several cases where this is insufficient:
|
However there are several cases where this is insufficient:
|
||||||
|
|
||||||
- I2C peripherals that require different drivers but have the same bus
|
- I2C peripherals that require different drivers but have the same bus address cannot be
|
||||||
address cannot be uniquely identified at runtime.
|
uniquely identified at runtime.
|
||||||
- A mainboard may be designed with multiple daughter board combinations
|
- A mainboard may be designed with multiple daughter board combinations which contain devices
|
||||||
which contain devices and configurations that cannot be detected.
|
and configurations that cannot be detected.
|
||||||
- While presence detect GPIOs are a convenient way for a single device
|
- While presence detect GPIOs are a convenient way for a single device presence, they are
|
||||||
presence, they are unable to distinguish between different devices so
|
unable to distinguish between different devices so it can require a large number of GPIOs to
|
||||||
it can require a large number of GPIOs to support relatively few
|
support relatively few options.
|
||||||
options.
|
|
||||||
|
|
||||||
This presence detection can impact different stages of boot:
|
This presence detection can impact different stages of boot:
|
||||||
|
|
||||||
|
|
||||||
### ACPI
|
### ACPI
|
||||||
|
|
||||||
Devices that are not present should not provide an ACPI device
|
Devices that are not present should not provide an ACPI device indicating that they are
|
||||||
indicating that they are present or the operating system may not be able
|
present or the operating system may not be able to handle it correctly.
|
||||||
to handle it correctly.
|
|
||||||
|
|
||||||
The ACPI devices are largely driven by chips defined in the mainboard
|
|
||||||
`devicetree.cb` and the variant overridetree.cb. This means it is
|
|
||||||
important to be able to specify when a device is present or not directly
|
|
||||||
in `devicetree.cb` itself. Otherwise each mainboard needs custom code to
|
|
||||||
parse the tree and disable unused devices.
|
|
||||||
|
|
||||||
|
The ACPI devices are largely driven by chips defined in the mainboard `devicetree.cb` and
|
||||||
|
the variant overridetree.cb. This means it is important to be able to specify when a device
|
||||||
|
is present or not directly in `devicetree.cb` itself. Otherwise each mainboard needs custom
|
||||||
|
code to parse the tree and disable unused devices.
|
||||||
|
|
||||||
### GPIO
|
### GPIO
|
||||||
|
|
||||||
GPIOs with multiple functions may need to be configured correctly
|
GPIOs with multiple functions may need to be configured correctly depending on the attached
|
||||||
depending on the attached device. Given the wide variety of GPIO
|
device. Given the wide variety of GPIO configuration possibilities it is not feasible to
|
||||||
configuration possibilities it is not feasible to specify all
|
specify all combinations directly in `devicetree.cb` and it is best left to code provided by
|
||||||
combinations directly in `devicetree.cb` and it is best left to code
|
the mainboard.
|
||||||
provided by the mainboard.
|
|
||||||
|
|
||||||
|
|
||||||
### FSP UPD
|
### FSP UPD
|
||||||
|
|
||||||
Enabling and disabling devices may require altering FSP UPD values that
|
Enabling and disabling devices may require altering FSP UPD values that are provided to the
|
||||||
are provided to the various stages of FSP. These options are also not
|
various stages of FSP. These options are also not easy to specify multiple times for
|
||||||
easy to specify multiple times for different configurations in
|
different configurations in `devicetree.cb` and can be provided by the mainboard as code.
|
||||||
`devicetree.cb` and can be provided by the mainboard as code.
|
|
||||||
|
|
||||||
|
|
||||||
## Firmware Configuration Interface
|
## Firmware Configuration Interface
|
||||||
|
|
||||||
The firmware configuration interface can be enabled by selecting
|
The firmware configuration interface can be enabled by selecting `CONFIG_FW_CONFIG` and also
|
||||||
`CONFIG_FW_CONFIG` and also providing a source for the value by defining
|
providing a source for the value by defining an additional Kconfig option defined below.
|
||||||
an additional Kconfig option defined below.
|
|
||||||
|
|
||||||
If the firmware configuration interface is disabled via Kconfig then all
|
|
||||||
probe attempts will return true.
|
|
||||||
|
|
||||||
|
If the firmware configuration interface is disabled via Kconfig then all probe attempts will
|
||||||
|
return true.
|
||||||
|
|
||||||
## Firmware Configuration Value
|
## Firmware Configuration Value
|
||||||
|
|
||||||
The 64-bit value used as the firmware configuration bitmask is meant to
|
The 64-bit value used as the firmware configuration bitmask is meant to be determined at runtime
|
||||||
be determined at runtime but could also be defined at compile time if
|
but could also be defined at compile time if needed.
|
||||||
needed.
|
|
||||||
|
|
||||||
There are two supported sources for providing this information to
|
|
||||||
coreboot.
|
|
||||||
|
|
||||||
|
There are two supported sources for providing this information to coreboot.
|
||||||
|
|
||||||
### CBFS
|
### CBFS
|
||||||
|
|
||||||
The value can be provided with a 64-bit raw value in CBFS that is read
|
The value can be provided with a 64-bit raw value in CBFS that is read by coreboot. The value
|
||||||
by coreboot. The value can be set at build time but also adjusted in an
|
can be set at build time but also adjusted in an existing image with `cbfstool`.
|
||||||
existing image with `cbfstool`.
|
|
||||||
|
|
||||||
To enable this select the `CONFIG_FW_CONFIG_CBFS` option in the build
|
To enable this select the `CONFIG_FW_CONFIG_CBFS` option in the build configuration and add a
|
||||||
configuration and add a raw 64-bit value to CBFS with the name of the
|
raw 64-bit value to CBFS with the name of the current prefix at `CONFIG_FW_PREFIX/fw_config`.
|
||||||
current prefix at `CONFIG_FW_PREFIX/fw_config`.
|
|
||||||
|
|
||||||
When `fw_config_probe_device()` or `fw_config_probe()` is called it will
|
|
||||||
look for the specified file in CBFS use the value it contains when
|
|
||||||
matching fields and options.
|
|
||||||
|
|
||||||
|
When `fw_config_probe_device()` or `fw_config_probe()` is called it will look for the specified
|
||||||
|
file in CBFS use the value it contains when matching fields and options.
|
||||||
|
|
||||||
### Embedded Controller
|
### Embedded Controller
|
||||||
|
|
||||||
Google ChromeOS devices support an Embedded Controller interface for
|
Google ChromeOS devices support an Embedded Controller interface for reading and writing the
|
||||||
reading and writing the firmware configuration value, along with other
|
firmware configuration value, along with other board-specific information. It is possible for
|
||||||
board-specific information. It is possible for coreboot to read this
|
coreboot to read this value at boot on systems that support this feature.
|
||||||
value at boot on systems that support this feature.
|
|
||||||
|
|
||||||
This option is selected by default for the mainboards that use it with
|
This option is selected by default for the mainboards that use it with
|
||||||
`CONFIG_FW_CONFIG_CHROME_EC_CBI` and it is not typically necessary to
|
`CONFIG_FW_CONFIG_CHROME_EC_CBI` and it is not typically necessary to adjust the value. It is
|
||||||
adjust the value. It is possible by enabling the CBFS source and
|
possible by enabling the CBFS source and coreboot will look in CBFS first for a valid value
|
||||||
coreboot will look in CBFS first for a valid value before asking the
|
before asking the embedded controller.
|
||||||
embedded controller.
|
|
||||||
|
|
||||||
It is also possible to adjust the value in the embedded controller
|
It is also possible to adjust the value in the embedded controller *(after disabling write
|
||||||
*(after disabling write protection)* with the `ectool` command in a
|
protection)* with the `ectool` command in a ChromeOS environment.
|
||||||
ChromeOS environment.
|
|
||||||
|
|
||||||
For more information on the firmware configuration field on ChromeOS
|
For more information on the firmware configuration field on ChromeOS devices see the Chromium
|
||||||
devices see the Chromium documentation for [Firmware Config][1] and
|
documentation for [Firmware Config][1] and [Board Info][2].
|
||||||
[Board Info][2].
|
|
||||||
|
|
||||||
[1]: http://chromium.googlesource.com/chromiumos/docs/+/HEAD/design_docs/firmware_config.md
|
[1]: http://chromium.googlesource.com/chromiumos/docs/+/HEAD/design_docs/firmware_config.md
|
||||||
[2]: http://chromium.googlesource.com/chromiumos/docs/+/HEAD/design_docs/cros_board_info.md
|
[2]: http://chromium.googlesource.com/chromiumos/docs/+/HEAD/design_docs/cros_board_info.md
|
||||||
|
|
||||||
|
|
||||||
## Firmware Configuration Table
|
## Firmware Configuration Table
|
||||||
|
|
||||||
The firmware configuration table itself is defined in the mainboard
|
The firmware configuration table itself is defined in the mainboard `devicetree.cb` with
|
||||||
`devicetree.cb` with special tokens for defining fields and options.
|
special tokens for defining fields and options.
|
||||||
|
|
||||||
The table itself is enclosed in a `fw_config` token and terminated with
|
The table itself is enclosed in a `fw_config` token and terminated with `end` and it contains
|
||||||
`end` and it contains a mix of field and option definitions.
|
a mix of field and option definitions.
|
||||||
|
|
||||||
Each field is defined by providing the field name and the start and end
|
Each field is defined by providing the field name and the start and end bit marking the exact
|
||||||
bit marking the exact location in the bitmask. Field names must be at
|
location in the bitmask. Field names must be at least three characters long in order to
|
||||||
least three characters long in order to satisfy the sconfig parser
|
satisfy the sconfig parser requirements and they must be unique with non-overlapping masks.
|
||||||
requirements and they must be unique with non-overlapping masks.
|
|
||||||
|
|
||||||
```text
|
field <name> <start-bit> <end-bit> [option...] end
|
||||||
field <name> <start-bit> <end-bit> [option...] end
|
|
||||||
```
|
|
||||||
|
|
||||||
For single-bit fields only one number is needed:
|
For single-bit fields only one number is needed:
|
||||||
|
|
||||||
```text
|
field <name> <bit> [option...] end
|
||||||
field <name> <bit> [option...] end
|
|
||||||
```
|
|
||||||
|
|
||||||
A field definition can also contain multiple sets of bit masks, which
|
A field definition can also contain multiple sets of bit masks, which can be dis-contiguous.
|
||||||
can be dis-contiguous. They are treated as if they are contiguous when
|
They are treated as if they are contiguous when defining option values. This allows for
|
||||||
defining option values. This allows for extending fields even after the
|
extending fields even after the bits after its current masks are occupied.
|
||||||
bits after its current masks are occupied.
|
|
||||||
|
|
||||||
```text
|
field <name> <start-bit0> <end-bit0> | <start-bit1> <end-bit1> | ...
|
||||||
field <name> <start-bit0> <end-bit0> | <start-bit1> <end-bit1> | ...
|
|
||||||
```
|
|
||||||
|
|
||||||
For example, if more audio options need to be supported:
|
For example, if more audio options need to be supported:
|
||||||
|
|
||||||
```text
|
field AUDIO 3 3
|
||||||
field AUDIO 3 3
|
option AUDIO_0 0
|
||||||
option AUDIO_0 0
|
option AUDIO_1 1
|
||||||
option AUDIO_1 1
|
end
|
||||||
end
|
field OTHER 4 4
|
||||||
field OTHER 4 4
|
...
|
||||||
...
|
end
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
the following can be done:
|
the following can be done:
|
||||||
|
|
||||||
```text
|
field AUDIO 3 3 | 5 5
|
||||||
field AUDIO 3 3 | 5 5
|
option AUDIO_FOO 0
|
||||||
option AUDIO_FOO 0
|
option AUDIO_BLAH 1
|
||||||
option AUDIO_BLAH 1
|
option AUDIO_BAR 2
|
||||||
option AUDIO_BAR 2
|
option AUDIO_BAZ 3
|
||||||
option AUDIO_BAZ 3
|
end
|
||||||
end
|
field OTHER 4 4
|
||||||
field OTHER 4 4
|
...
|
||||||
...
|
end
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
In that case, the AUDIO masks are extended like so:
|
In that case, the AUDIO masks are extended like so:
|
||||||
|
|
||||||
```c
|
#define FW_CONFIG_FIELD_AUDIO_MASK 0x28
|
||||||
#define FW_CONFIG_FIELD_AUDIO_MASK 0x28
|
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_FOO_VALUE 0x0
|
||||||
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_FOO_VALUE 0x0
|
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_BLAH_VALUE 0x8
|
||||||
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_BLAH_VALUE 0x8
|
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_BAR_VALUE 0x20
|
||||||
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_BAR_VALUE 0x20
|
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_BAz_VALUE 0x28
|
||||||
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_BAz_VALUE 0x28
|
|
||||||
```
|
|
||||||
|
|
||||||
Each `field` definition starts a new block that can be composed of zero
|
Each `field` definition starts a new block that can be composed of zero or more field options,
|
||||||
or more field options, and it is terminated with `end`.
|
and it is terminated with `end`.
|
||||||
|
|
||||||
Inside the field block the options can be defined by providing the
|
Inside the field block the options can be defined by providing the option name and the field
|
||||||
option name and the field value that this option represents when the bit
|
value that this option represents when the bit offsets are used to apply a mask and shift.
|
||||||
offsets are used to apply a mask and shift. Option names must also be at
|
Option names must also be at least three characters for the sconfig parser.
|
||||||
least three characters for the sconfig parser.
|
|
||||||
|
|
||||||
```text
|
option <name> <value>
|
||||||
option <name> <value>
|
|
||||||
```
|
|
||||||
|
|
||||||
It is possible for there to be multiple `fw_config` blocks and for
|
It is possible for there to be multiple `fw_config` blocks and for subsequent `field` blocks
|
||||||
subsequent `field` blocks to add additional `option` definitions to the
|
to add additional `option` definitions to the existing field. These subsequent definitions
|
||||||
existing field. These subsequent definitions should not provide the
|
should not provide the field bitmask as it has already been defined earlier in the file and
|
||||||
field bitmask as it has already been defined earlier in the file and
|
|
||||||
this is just matching an existing field by name.
|
this is just matching an existing field by name.
|
||||||
|
|
||||||
```text
|
field <name> [option...] end
|
||||||
field <name> [option...] end
|
|
||||||
```
|
|
||||||
|
|
||||||
This allows a baseboard to define the major fields and options in
|
This allows a baseboard to define the major fields and options in `devicetree.cb` and a board
|
||||||
`devicetree.cb` and a board variant to add specific options to fields in
|
variant to add specific options to fields in or define new fields in the unused bitmask in
|
||||||
or define new fields in the unused bitmask in `overridetree.cb`.
|
`overridetree.cb`.
|
||||||
|
|
||||||
It is not possible to redefine a field mask or override the value of an
|
|
||||||
existing option this way, only to add new options to a field or new
|
|
||||||
fields to the table.
|
|
||||||
|
|
||||||
|
It is not possible to redefine a field mask or override the value of an existing option this
|
||||||
|
way, only to add new options to a field or new fields to the table.
|
||||||
|
|
||||||
### Firmware Configuration Table Example
|
### Firmware Configuration Table Example
|
||||||
|
|
||||||
In this example a baseboard defines a simple boolean feature that is
|
In this example a baseboard defines a simple boolean feature that is enabled or disabled
|
||||||
enabled or disabled depending on the value of bit 0, and a field at bits
|
depending on the value of bit 0, and a field at bits 1-2 that indicates which daughter board
|
||||||
1-2 that indicates which daughter board is attached.
|
is attached.
|
||||||
|
|
||||||
The baseboard itself defines one daughter board and the variant adds two
|
|
||||||
more possibilities. This way each variant can support multiple possible
|
|
||||||
daughter boards in addition to the one that was defined by the
|
|
||||||
baseboard.
|
|
||||||
|
|
||||||
|
The baseboard itself defines one daughter board and the variant adds two more possibilities.
|
||||||
|
This way each variant can support multiple possible daughter boards in addition to the one
|
||||||
|
that was defined by the baseboard.
|
||||||
|
|
||||||
#### devicetree.cb
|
#### devicetree.cb
|
||||||
|
|
||||||
```text
|
fw_config
|
||||||
fw_config
|
field FEATURE 0
|
||||||
field FEATURE 0
|
option DISABLED 0
|
||||||
option DISABLED 0
|
option ENABLED 1
|
||||||
option ENABLED 1
|
end
|
||||||
|
field DAUGHTER_BOARD 1 2
|
||||||
|
option NONE 0
|
||||||
|
option REFERENCE_DB 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
field DAUGHTER_BOARD 1 2
|
|
||||||
option NONE 0
|
|
||||||
option REFERENCE_DB 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### overridetree.cb
|
#### overridetree.cb
|
||||||
|
|
||||||
```text
|
fw_config
|
||||||
fw_config
|
field DAUGHTER_BOARD
|
||||||
field DAUGHTER_BOARD
|
option VARIANT_DB_ONE 2
|
||||||
option VARIANT_DB_ONE 2
|
option VARIANT_DB_TWO 3
|
||||||
option VARIANT_DB_TWO 3
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
The result of this table defined in `devicetree.cb` is a list of
|
|
||||||
constants that can be used to check if fields match the firmware
|
|
||||||
configuration options determined at runtime with a simple check of the
|
|
||||||
field mask and the option value.
|
|
||||||
|
|
||||||
|
The result of this table defined in `devicetree.cb` is a list of constants that can be used
|
||||||
|
to check if fields match the firmware configuration options determined at runtime with a
|
||||||
|
simple check of the field mask and the option value.
|
||||||
|
|
||||||
#### static.h
|
#### static.h
|
||||||
|
|
||||||
|
|
@ -305,96 +246,73 @@ field mask and the option value.
|
||||||
#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_VALUE 0x00000006
|
#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_VALUE 0x00000006
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Device Probing
|
## Device Probing
|
||||||
|
|
||||||
One use of the firmware configuration interface in devicetree is to
|
One use of the firmware configuration interface in devicetree is to allow device probing to be
|
||||||
allow device probing to be specified directly with the devices
|
specified directly with the devices themselves. A new `probe` token is introduced to allow a
|
||||||
themselves. A new `probe` token is introduced to allow a device to be
|
device to be probed by field and option name. Multiple `probe` entries may be present for
|
||||||
probed by field and option name. Multiple `probe` entries may be present
|
each device and any successful probe will consider the device to be present.
|
||||||
for each device and any successful probe will consider the device to be
|
|
||||||
present.
|
|
||||||
|
|
||||||
|
|
||||||
### Probing Example
|
### Probing Example
|
||||||
|
|
||||||
Continuing with the previous example this device would be considered
|
Continuing with the previous example this device would be considered present if the field
|
||||||
present if the field `DAUGHTER_BOARD` was set to either `VARIANT_DB_ONE`
|
`DAUGHTER_BOARD` was set to either `VARIANT_DB_ONE` or `VARIANT_DB_TWO`:
|
||||||
or `VARIANT_DB_TWO`:
|
|
||||||
|
|
||||||
|
|
||||||
#### overridetree.cb
|
#### overridetree.cb
|
||||||
|
|
||||||
```text
|
chip drivers/generic/example
|
||||||
chip drivers/generic/example
|
device generic 0 on
|
||||||
device generic 0 on
|
probe DAUGHTER_BOARD VARIANT_DB_ONE
|
||||||
probe DAUGHTER_BOARD VARIANT_DB_ONE
|
probe DAUGHTER_BOARD VARIANT_DB_TWO
|
||||||
probe DAUGHTER_BOARD VARIANT_DB_TWO
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
If the field were set to any other option, including `NONE` and
|
|
||||||
`REFERENCE_DB` and any undefined value then the device would be
|
|
||||||
disabled.
|
|
||||||
|
|
||||||
|
If the field were set to any other option, including `NONE` and `REFERENCE_DB` and any
|
||||||
|
undefined value then the device would be disabled.
|
||||||
|
|
||||||
### Probe Overrides
|
### Probe Overrides
|
||||||
|
|
||||||
When a device is declared with a probe in the baseboard `devicetree.cb`
|
When a device is declared with a probe in the baseboard `devicetree.cb` and the same device
|
||||||
and the same device is also present in the `overridetree.cb` then the
|
is also present in the `overridetree.cb` then the probing information from the baseboard
|
||||||
probing information from the baseboard is discarded and the override
|
is discarded and the override device must provide all necessary probing information.
|
||||||
device must provide all necessary probing information.
|
|
||||||
|
|
||||||
In this example a device is listed in the baseboard with
|
In this example a device is listed in the baseboard with `DAUGHTER_BOARD` field probing for
|
||||||
`DAUGHTER_BOARD` field probing for `REFERENCE_DB` as a field option, It
|
`REFERENCE_DB` as a field option, It is also defined as an override device with the field
|
||||||
is also defined as an override device with the field probing for the
|
probing for the `VARIANT_DB_ONE` option instead.
|
||||||
`VARIANT_DB_ONE` option instead.
|
|
||||||
|
|
||||||
In this case only the probe listed in the override is checked and a
|
|
||||||
field option of `REFERENCE_DB` will not mark this device present. If
|
|
||||||
both options are desired then the override device must list both. This
|
|
||||||
allows an override device to remove a probe entry that was defined in
|
|
||||||
the baseboard.
|
|
||||||
|
|
||||||
|
In this case only the probe listed in the override is checked and a field option of
|
||||||
|
`REFERENCE_DB` will not mark this device present. If both options are desired then the
|
||||||
|
override device must list both. This allows an override device to remove a probe entry that
|
||||||
|
was defined in the baseboard.
|
||||||
|
|
||||||
#### devicetree.cb
|
#### devicetree.cb
|
||||||
|
|
||||||
```text
|
chip drivers/generic/example
|
||||||
chip drivers/generic/example
|
device generic 0 on
|
||||||
device generic 0 on
|
probe DAUGHTER_BOARD REFERENCE_DB
|
||||||
probe DAUGHTER_BOARD REFERENCE_DB
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### overridetree.cb
|
#### overridetree.cb
|
||||||
|
|
||||||
```text
|
chip drivers/generic/example
|
||||||
chip drivers/generic/example
|
device generic 0 on
|
||||||
device generic 0 on
|
probe DAUGHTER_BOARD VARIANT_DB_ONE
|
||||||
probe DAUGHTER_BOARD VARIANT_DB_ONE
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Automatic Device Probing
|
### Automatic Device Probing
|
||||||
|
|
||||||
At boot time the firmware configuration interface will walk the device
|
At boot time the firmware configuration interface will walk the device tree and apply any
|
||||||
tree and apply any probe entries that were defined in `devicetree.cb`.
|
probe entries that were defined in `devicetree.cb`. This probing takes effect before the
|
||||||
This probing takes effect before the `BS_DEV_ENUMERATE` step during the
|
`BS_DEV_ENUMERATE` step during the boot state machine in ramstage.
|
||||||
boot state machine in ramstage.
|
|
||||||
|
|
||||||
Devices that have a probe list but do do not find a match are disabled
|
Devices that have a probe list but do do not find a match are disabled by setting
|
||||||
by setting `dev->enabled = 0` but the chip `enable_dev()` and device
|
`dev->enabled = 0` but the chip `enable_dev()` and device `enable()` handlers will still
|
||||||
`enable()` handlers will still be executed to allow any device disable
|
be executed to allow any device disable code to execute.
|
||||||
code to execute.
|
|
||||||
|
|
||||||
The result of this probe definition is to provide an array of structures
|
|
||||||
describing each field and option to check.
|
|
||||||
|
|
||||||
|
The result of this probe definition is to provide an array of structures describing each
|
||||||
|
field and option to check.
|
||||||
|
|
||||||
#### fw_config.h
|
#### fw_config.h
|
||||||
|
|
||||||
|
|
@ -407,43 +325,40 @@ describing each field and option to check.
|
||||||
* @value: Value of the option within the mask.
|
* @value: Value of the option within the mask.
|
||||||
*/
|
*/
|
||||||
struct fw_config {
|
struct fw_config {
|
||||||
const char *field_name;
|
const char *field_name;
|
||||||
const char *option_name;
|
const char *option_name;
|
||||||
uint64_t mask;
|
uint64_t mask;
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
#### static.c
|
#### static.c
|
||||||
|
|
||||||
```c
|
```c
|
||||||
STORAGE struct fw_config __devN_probe_list[] = {
|
STORAGE struct fw_config __devN_probe_list[] = {
|
||||||
{
|
{
|
||||||
.field_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_NAME,
|
.field_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_NAME,
|
||||||
.option_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_NAME,
|
.option_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_NAME,
|
||||||
.mask = FW_CONFIG_FIELD_DAUGHTER_BOARD_MASK,
|
.mask = FW_CONFIG_FIELD_DAUGHTER_BOARD_MASK,
|
||||||
.value = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_VALUE
|
.value = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_VALUE
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.field_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_NAME,
|
.field_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_NAME,
|
||||||
.option_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_NAME,
|
.option_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_NAME,
|
||||||
.mask = FW_CONFIG_FIELD_DAUGHTER_BOARD_MASK,
|
.mask = FW_CONFIG_FIELD_DAUGHTER_BOARD_MASK,
|
||||||
.value = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_VALUE
|
.value = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_VALUE
|
||||||
},
|
},
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Runtime Probing
|
### Runtime Probing
|
||||||
|
|
||||||
The device driver probing allows for seamless integration with the
|
The device driver probing allows for seamless integration with the mainboard but it is only
|
||||||
mainboard but it is only effective in ramstage and for specific devices
|
effective in ramstage and for specific devices declared in devicetree.cb. There are other
|
||||||
declared in devicetree.cb. There are other situations where code may
|
situations where code may need to probe or check the value of a field in romstage or at other
|
||||||
need to probe or check the value of a field in romstage or at other
|
points in ramstage. For this reason it is also possible to use the firmware configuration
|
||||||
points in ramstage. For this reason it is also possible to use the
|
interface directly.
|
||||||
firmware configuration interface directly.
|
|
||||||
|
|
||||||
```c
|
```c
|
||||||
/**
|
/**
|
||||||
|
|
@ -457,21 +372,18 @@ bool fw_config_probe(const struct fw_config *match);
|
||||||
|
|
||||||
The argument provided to this function can be created from a macro for easy use:
|
The argument provided to this function can be created from a macro for easy use:
|
||||||
|
|
||||||
```text
|
FW_CONFIG(field, option)
|
||||||
FW_CONFIG(field, option)
|
|
||||||
```
|
|
||||||
|
|
||||||
This example has a mainboard check if a feature is disabled and set an
|
This example has a mainboard check if a feature is disabled and set an FSP UPD before memory
|
||||||
FSP UPD before memory training. This example expects that the default
|
training. This example expects that the default value of this `register` is set to `true` in
|
||||||
value of this `register` is set to `true` in `devicetree.cb` and this
|
`devicetree.cb` and this code is disabling that feature before FSP is executed.
|
||||||
code is disabling that feature before FSP is executed.
|
|
||||||
|
|
||||||
```c
|
```c
|
||||||
#include <fw_config.h>
|
#include <fw_config.h>
|
||||||
|
|
||||||
void mainboard_memory_init_params(FSPM_UPD *mupd)
|
void mainboard_memory_init_params(FSPM_UPD *mupd)
|
||||||
{
|
{
|
||||||
if (fw_config_probe(FW_CONFIG(FEATURE, DISABLED))
|
if (fw_config_probe(FW_CONFIG(FEATURE, DISABLED))
|
||||||
mupd->ExampleFeature = false;
|
mupd->ExampleFeature = false;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,7 @@
|
||||||
This section contains documentation about coreboot internal technical
|
This section contains documentation about coreboot internal technical
|
||||||
information and libraries.
|
information and libraries.
|
||||||
|
|
||||||
```{toctree}
|
- [Flashmap and Flashmap Descriptor](flashmap.md)
|
||||||
:maxdepth: 1
|
- [ABI data consumption](abi-data-consumption.md)
|
||||||
|
- [Timestamps](timestamp.md)
|
||||||
Flashmap and Flashmap Descriptor <flashmap.md>
|
- [Firmware Configuration Interface](fw_config.md)
|
||||||
ABI data consumption <abi-data-consumption.md>
|
|
||||||
Timestamps <timestamp.md>
|
|
||||||
Firmware Configuration Interface <fw_config.md>
|
|
||||||
Relocatable Modules <rmodules.md>
|
|
||||||
Timers, Stopwatch, and Delays <stopwatch.md>
|
|
||||||
Threads <threads.md>
|
|
||||||
Ramstage Bootstates & Bootstate Callbacks <ramstage_bootstates.md>
|
|
||||||
```
|
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,4 @@ selected mainboard.
|
||||||
|
|
||||||
## FIT
|
## FIT
|
||||||
|
|
||||||
```{toctree}
|
- [uImage.FIT support](fit.md)
|
||||||
:maxdepth: 1
|
|
||||||
|
|
||||||
uImage.FIT support <fit.md>
|
|
||||||
```
|
|
||||||
|
|
|
||||||
|
|
@ -1,514 +0,0 @@
|
||||||
# coreboot Ramstage Bootstates & Bootstate Callbacks
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
|
|
||||||
The coreboot boot process is divided into several discrete phases, one
|
|
||||||
of which is **ramstage**. Ramstage is the phase where the main hardware
|
|
||||||
initialization and device setup occurs after memory initialization.
|
|
||||||
Within ramstage, a state machine called the **bootstate machine**
|
|
||||||
manages the sequence of operations needed to initialize the system,
|
|
||||||
configure devices, and prepare to load and execute the payload (such as
|
|
||||||
a bootloader, operating system, or firmware utility).
|
|
||||||
|
|
||||||
The bootstate machine provides a structured and extensible way to
|
|
||||||
organize code execution during the boot process. It allows for clear
|
|
||||||
separation of concerns between different initialization phases and
|
|
||||||
provides hooks for component-specific code to run at well-defined
|
|
||||||
points.
|
|
||||||
|
|
||||||
**Important Note:** The exact execution order of multiple callbacks
|
|
||||||
registered for the same state and sequence (entry/exit) is not
|
|
||||||
guaranteed. This means that you cannot depend on one call for the
|
|
||||||
state/sequence in any other calls to the same state/sequence. If this
|
|
||||||
ordering is required, join the calls to the two functions into a single
|
|
||||||
function which specifies the order and create a callback to call the
|
|
||||||
top-level function instead of the two individual callbacks.
|
|
||||||
|
|
||||||
|
|
||||||
## Bootstate Machine Architecture
|
|
||||||
|
|
||||||
The bootstate machine's public API is defined in
|
|
||||||
`src/include/bootstate.h`, and its core implementation resides in
|
|
||||||
`src/lib/hardwaremain.c`. At its core, it consists of:
|
|
||||||
|
|
||||||
1. A series of sequential states that represent phases of the boot process
|
|
||||||
2. A mechanism for callback registration to execute code during state transitions
|
|
||||||
3. A framework for blocking and unblocking state transitions
|
|
||||||
4. Timing and debugging facilities to measure and report performance during boot
|
|
||||||
|
|
||||||
|
|
||||||
### Key Data Structures
|
|
||||||
|
|
||||||
The primary public data structure for interacting with the bootstate
|
|
||||||
machine is `struct boot_state_callback`. The internal implementation
|
|
||||||
also uses `struct boot_state` and `struct boot_phase`.
|
|
||||||
|
|
||||||
|
|
||||||
#### Boot State Callback (Public API)
|
|
||||||
|
|
||||||
Callbacks that run during state transitions are defined by this
|
|
||||||
structure in `src/include/bootstate.h`:
|
|
||||||
|
|
||||||
```c
|
|
||||||
struct boot_state_callback {
|
|
||||||
void *arg; // Argument to pass to the callback
|
|
||||||
void (*callback)(void *arg); // Function pointer to the callback
|
|
||||||
struct boot_state_callback *next; // Next callback in linked list (internal use)
|
|
||||||
#if CONFIG(DEBUG_BOOT_STATE)
|
|
||||||
const char *location; // Source location for debugging
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Boot State Sequence (Public API)
|
|
||||||
|
|
||||||
The boot state sequence type, defined in `src/include/bootstate.h`,
|
|
||||||
specifies when a callback should run relative to the state's main
|
|
||||||
action:
|
|
||||||
|
|
||||||
```c
|
|
||||||
typedef enum {
|
|
||||||
BS_ON_ENTRY, // Execute before state function
|
|
||||||
BS_ON_EXIT // Execute after state function
|
|
||||||
} boot_state_sequence_t;
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### Boot State (Internal Implementation)
|
|
||||||
|
|
||||||
The main internal data structure in `src/lib/hardwaremain.c` is
|
|
||||||
`struct boot_state`, which defines a single state in the bootstate
|
|
||||||
machine:
|
|
||||||
|
|
||||||
```c
|
|
||||||
struct boot_state {
|
|
||||||
const char *name; // Human-readable name of the state
|
|
||||||
boot_state_t id; // Enumerated identifier for the state
|
|
||||||
u8 post_code; // POST code to output during state execution
|
|
||||||
struct boot_phase phases[2]; // Entry and exit phases (internal use)
|
|
||||||
boot_state_t (*run_state)(void *arg); // Function to execute during the state
|
|
||||||
void *arg; // Argument to pass to the run_state function
|
|
||||||
int num_samples; // Counter for timing samples (internal use)
|
|
||||||
bool complete; // Flag indicating if state has completed (internal use)
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### Boot Phase (Internal Implementation)
|
|
||||||
|
|
||||||
Each boot state has two internal phases ("entry" and "exit") represented
|
|
||||||
by `struct boot_phase` in `src/lib/hardwaremain.c`:
|
|
||||||
|
|
||||||
```c
|
|
||||||
struct boot_phase {
|
|
||||||
struct boot_state_callback *callbacks; // Linked list of callbacks
|
|
||||||
int blockers; // Counter for blocking state transition
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## Bootstate Sequence
|
|
||||||
|
|
||||||
The bootstate machine defines the following sequence of states, executed
|
|
||||||
in order by the `bs_walk_state_machine` function in
|
|
||||||
`src/lib/hardwaremain.c`. The sequence is defined by the `boot_state_t`
|
|
||||||
enum in `src/include/bootstate.h`:
|
|
||||||
|
|
||||||
1. **BS_PRE_DEVICE**: Initial state before any device operations begin
|
|
||||||
2. **BS_DEV_INIT_CHIPS**: Early chip initialization for critical components
|
|
||||||
3. **BS_DEV_ENUMERATE**: Device enumeration (discovering devices on buses)
|
|
||||||
4. **BS_DEV_RESOURCES**: Resource allocation for devices
|
|
||||||
5. **BS_DEV_ENABLE**: Enabling devices that were discovered
|
|
||||||
6. **BS_DEV_INIT**: Device initialization
|
|
||||||
7. **BS_POST_DEVICE**: All device operations have been completed
|
|
||||||
8. **BS_OS_RESUME_CHECK**: Check if we're resuming from a sleep state
|
|
||||||
9. **BS_OS_RESUME**: Handle OS resume process (if needed)
|
|
||||||
10. **BS_WRITE_TABLES**: Write system tables (e.g., ACPI, SMBIOS)
|
|
||||||
11. **BS_PAYLOAD_LOAD**: Load the payload into memory
|
|
||||||
12. **BS_PAYLOAD_BOOT**: Boot the payload
|
|
||||||
|
|
||||||
This sequence forms the backbone of the ramstage execution flow. Each
|
|
||||||
state performs a specific task, runs associated callbacks, and
|
|
||||||
transitions to the next state upon completion, unless blocked.
|
|
||||||
|
|
||||||
|
|
||||||
## Bootstate Details
|
|
||||||
|
|
||||||
### BS_PRE_DEVICE
|
|
||||||
|
|
||||||
**Purpose**: Serves as the initial state before any device tree
|
|
||||||
operations begin.
|
|
||||||
|
|
||||||
**Key Functions**:
|
|
||||||
- `bs_pre_device()`: Sets up initial environment and transitions to next
|
|
||||||
state.
|
|
||||||
|
|
||||||
**Usage**: This state is used for initializing core components that need
|
|
||||||
to be set up before any device operations. Examples include:
|
|
||||||
- Setting up global NVRAM variables
|
|
||||||
- Initializing debugging facilities
|
|
||||||
- Preparing ACPI tables or other critical system structures
|
|
||||||
|
|
||||||
|
|
||||||
### BS_DEV_INIT_CHIPS
|
|
||||||
|
|
||||||
**Purpose**: Initializes critical chips early in the boot process.
|
|
||||||
|
|
||||||
**Key Functions**:
|
|
||||||
- `bs_dev_init_chips()`: Calls `dev_initialize_chips()` to initialize
|
|
||||||
all chips in the device tree.
|
|
||||||
|
|
||||||
**Notes**: Chip initialization can disable unused devices, which is why
|
|
||||||
it happens before device enumeration.
|
|
||||||
|
|
||||||
|
|
||||||
### BS_DEV_ENUMERATE
|
|
||||||
|
|
||||||
**Purpose**: Discovers devices in the system.
|
|
||||||
|
|
||||||
**Key Functions**:
|
|
||||||
- `bs_dev_enumerate()`: Calls `dev_enumerate()` to probe and identify
|
|
||||||
devices.
|
|
||||||
|
|
||||||
**Notes**: During this phase, the system scans buses and detects
|
|
||||||
connected devices.
|
|
||||||
|
|
||||||
|
|
||||||
### BS_DEV_RESOURCES
|
|
||||||
|
|
||||||
**Purpose**: Allocates and assigns resources (I/O, memory, IRQs) to
|
|
||||||
devices.
|
|
||||||
|
|
||||||
**Key Functions**:
|
|
||||||
- `bs_dev_resources()`: Calls `dev_configure()` to compute and assign
|
|
||||||
bus resources.
|
|
||||||
|
|
||||||
**Notes**: Resource allocation resolves conflicts and ensures each
|
|
||||||
device has the resources it needs.
|
|
||||||
|
|
||||||
|
|
||||||
### BS_DEV_ENABLE
|
|
||||||
|
|
||||||
**Purpose**: Enables devices in the system.
|
|
||||||
|
|
||||||
**Key Functions**:
|
|
||||||
- `bs_dev_enable()`: Calls `dev_enable()` to enable devices on the bus.
|
|
||||||
|
|
||||||
**Notes**: Some devices may be selectively disabled based on hardware
|
|
||||||
configuration or policy.
|
|
||||||
|
|
||||||
|
|
||||||
### BS_DEV_INIT
|
|
||||||
|
|
||||||
**Purpose**: Initializes enabled devices.
|
|
||||||
|
|
||||||
**Key Functions**:
|
|
||||||
- `bs_dev_init()`: Calls `dev_initialize()` to initialize devices on the
|
|
||||||
bus.
|
|
||||||
|
|
||||||
**Notes**: This state performs device-specific initialization routines
|
|
||||||
for all enabled devices.
|
|
||||||
|
|
||||||
|
|
||||||
### BS_POST_DEVICE
|
|
||||||
|
|
||||||
**Purpose**: Final state after all device operations have completed.
|
|
||||||
|
|
||||||
**Key Functions**:
|
|
||||||
- `bs_post_device()`: Calls `dev_finalize()` to complete any final
|
|
||||||
device operations.
|
|
||||||
|
|
||||||
**Notes**: This state serves as a checkpoint that all device
|
|
||||||
initialization is complete.
|
|
||||||
|
|
||||||
|
|
||||||
### BS_OS_RESUME_CHECK
|
|
||||||
|
|
||||||
**Purpose**: Checks if the system should resume from a sleep state.
|
|
||||||
|
|
||||||
**Key Functions**:
|
|
||||||
- `bs_os_resume_check()`: Looks for a wake vector to determine if resume
|
|
||||||
is needed.
|
|
||||||
|
|
||||||
**Notes**: This state branches the boot flow based on whether the system
|
|
||||||
is resuming from a sleep state.
|
|
||||||
|
|
||||||
### BS_OS_RESUME
|
|
||||||
|
|
||||||
**Purpose**: Handles the OS resume process.
|
|
||||||
|
|
||||||
**Key Functions**:
|
|
||||||
- `bs_os_resume()`: Calls `acpi_resume()` with the wake vector to resume
|
|
||||||
the OS.
|
|
||||||
|
|
||||||
**Notes**: After successful resume, control is transferred to the OS and
|
|
||||||
does not return to coreboot.
|
|
||||||
|
|
||||||
|
|
||||||
### BS_WRITE_TABLES
|
|
||||||
|
|
||||||
**Purpose**: Writes configuration tables for the payload or OS.
|
|
||||||
|
|
||||||
**Key Functions**:
|
|
||||||
- `bs_write_tables()`: Calls `write_tables()` to generate system tables.
|
|
||||||
|
|
||||||
**Notes**: Tables include ACPI, SMBIOS, and other system configuration
|
|
||||||
data.
|
|
||||||
|
|
||||||
|
|
||||||
### BS_PAYLOAD_LOAD
|
|
||||||
|
|
||||||
**Purpose**: Loads the payload into memory.
|
|
||||||
|
|
||||||
**Key Functions**:
|
|
||||||
- `bs_payload_load()`: Calls `payload_load()` to load the payload.
|
|
||||||
|
|
||||||
**Notes**: The payload could be a bootloader, an operating system kernel,
|
|
||||||
or a firmware utility.
|
|
||||||
|
|
||||||
|
|
||||||
### BS_PAYLOAD_BOOT
|
|
||||||
|
|
||||||
**Purpose**: Final state that boots the loaded payload.
|
|
||||||
|
|
||||||
**Key Functions**:
|
|
||||||
- `bs_payload_boot()`: Calls `payload_run()` to execute the payload.
|
|
||||||
|
|
||||||
**Notes**: After successful execution, control is transferred to the
|
|
||||||
payload and does not return to coreboot. If execution returns (which
|
|
||||||
indicates an error), a boot failure message is printed.
|
|
||||||
|
|
||||||
|
|
||||||
## Driving the State Machine
|
|
||||||
|
|
||||||
The state machine is driven by the `main()` function in
|
|
||||||
`src/lib/hardwaremain.c`. After initial setup (like initializing the
|
|
||||||
console and CBMEM), it calls `bs_walk_state_machine()`.
|
|
||||||
|
|
||||||
`bs_walk_state_machine()` loops through the defined boot states:
|
|
||||||
1. It identifies the current state.
|
|
||||||
2. Runs all `BS_ON_ENTRY` callbacks for that state.
|
|
||||||
3. Executes the state's specific function (e.g., `bs_dev_enumerate()`).
|
|
||||||
4. Runs all `BS_ON_EXIT` callbacks for that state.
|
|
||||||
5. Transitions to the next state returned by the state function.
|
|
||||||
|
|
||||||
This loop continues until the final state (`BS_PAYLOAD_BOOT` or
|
|
||||||
`BS_OS_RESUME`) transfers control away from coreboot.
|
|
||||||
|
|
||||||
|
|
||||||
## External Functions (Public API)
|
|
||||||
|
|
||||||
The bootstate machine provides several functions in
|
|
||||||
`src/include/bootstate.h` for interacting with states:
|
|
||||||
|
|
||||||
|
|
||||||
### Callback Registration
|
|
||||||
|
|
||||||
```c
|
|
||||||
int boot_state_sched_on_entry(struct boot_state_callback *bscb, boot_state_t state_id);
|
|
||||||
```
|
|
||||||
Schedules a callback to run when entering a state (`BS_ON_ENTRY`).
|
|
||||||
|
|
||||||
```c
|
|
||||||
int boot_state_sched_on_exit(struct boot_state_callback *bscb, boot_state_t state_id);
|
|
||||||
```
|
|
||||||
Schedules a callback to run when exiting a state (`BS_ON_EXIT`).
|
|
||||||
|
|
||||||
|
|
||||||
### State Transition Control
|
|
||||||
|
|
||||||
```c
|
|
||||||
int boot_state_block(boot_state_t state, boot_state_sequence_t seq);
|
|
||||||
```
|
|
||||||
Blocks a state transition from occurring after the specified sequence
|
|
||||||
(entry or exit callbacks). The transition will pause until the block is
|
|
||||||
removed.
|
|
||||||
|
|
||||||
```c
|
|
||||||
int boot_state_unblock(boot_state_t state, boot_state_sequence_t seq);
|
|
||||||
```
|
|
||||||
Removes a previously set block on a state transition.
|
|
||||||
|
|
||||||
|
|
||||||
### Static Callback Registration
|
|
||||||
|
|
||||||
For registering callbacks at compile time, use the `BOOT_STATE_INIT_ENTRY`
|
|
||||||
macro defined in `src/include/bootstate.h`:
|
|
||||||
|
|
||||||
```c
|
|
||||||
BOOT_STATE_INIT_ENTRY(state, when, func, arg)
|
|
||||||
```
|
|
||||||
|
|
||||||
This macro creates a static entry in a special section (`.bs_init`) of
|
|
||||||
the binary. These entries are processed early in `main()` by
|
|
||||||
`boot_state_schedule_static_entries()` to register the callbacks before
|
|
||||||
the state machine starts running.
|
|
||||||
|
|
||||||
|
|
||||||
## Configuration Options
|
|
||||||
|
|
||||||
The bootstate machine behavior can be modified through Kconfig options:
|
|
||||||
|
|
||||||
|
|
||||||
### DEBUG_BOOT_STATE
|
|
||||||
|
|
||||||
```
|
|
||||||
config DEBUG_BOOT_STATE
|
|
||||||
bool "Debug boot state machine"
|
|
||||||
default n
|
|
||||||
help
|
|
||||||
Control debugging of the boot state machine. When selected displays
|
|
||||||
the state boundaries in ramstage.
|
|
||||||
```
|
|
||||||
|
|
||||||
When enabled, this option causes the bootstate machine to output
|
|
||||||
debugging information via `printk`, including:
|
|
||||||
- State transition notifications (`Entering/Exiting <state> state.`)
|
|
||||||
- Callback execution details (address, source location, execution time)
|
|
||||||
- Timing information for state execution phases (entry, run, exit)
|
|
||||||
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
### Adding a New Bootstate Callback
|
|
||||||
|
|
||||||
To register a function to be called when entering a specific state using
|
|
||||||
the static registration method:
|
|
||||||
|
|
||||||
```c
|
|
||||||
// Function to be called
|
|
||||||
static void my_init_function(void *arg)
|
|
||||||
{
|
|
||||||
// Initialization code
|
|
||||||
printk(BIOS_DEBUG, "My initialization running...\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register the callback at compile time
|
|
||||||
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, my_init_function, NULL);
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Runtime Callback Registration
|
|
||||||
|
|
||||||
For dynamic callback registration during runtime (e.g., within another
|
|
||||||
callback or state function):
|
|
||||||
|
|
||||||
```c
|
|
||||||
static void runtime_init(void *arg)
|
|
||||||
{
|
|
||||||
// Do something
|
|
||||||
}
|
|
||||||
|
|
||||||
void register_my_callbacks(void)
|
|
||||||
{
|
|
||||||
// Allocate or define a static callback structure
|
|
||||||
static struct boot_state_callback bscb = {
|
|
||||||
.callback = runtime_init,
|
|
||||||
.arg = NULL,
|
|
||||||
// .location is automatically handled if DEBUG_BOOT_STATE=y
|
|
||||||
};
|
|
||||||
|
|
||||||
// Schedule it
|
|
||||||
boot_state_sched_on_entry(&bscb, BS_DEV_ENABLE);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Blocking State Transition
|
|
||||||
|
|
||||||
To temporarily block a state from progressing until a condition is met,
|
|
||||||
often used with timers:
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h> // Required for timer functions
|
|
||||||
|
|
||||||
static void wait_for_device(void *arg)
|
|
||||||
{
|
|
||||||
if (!device_is_ready()) {
|
|
||||||
// Block the transition *after* BS_DEV_INIT exits
|
|
||||||
boot_state_block(BS_DEV_INIT, BS_ON_EXIT);
|
|
||||||
|
|
||||||
// Schedule a function to check again later (e.g., after 100us)
|
|
||||||
// Assume schedule_timer exists and works appropriately
|
|
||||||
schedule_timer(check_device_ready, NULL, 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void check_device_ready(void *arg)
|
|
||||||
{
|
|
||||||
if (device_is_ready()) {
|
|
||||||
// Device is ready, unblock the transition
|
|
||||||
boot_state_unblock(BS_DEV_INIT, BS_ON_EXIT);
|
|
||||||
} else {
|
|
||||||
// Still not ready, check again later
|
|
||||||
schedule_timer(check_device_ready, NULL, 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register the initial check to run when entering BS_DEV_INIT
|
|
||||||
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, wait_for_device, NULL);
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Best Practices
|
|
||||||
|
|
||||||
### When Working with Bootstates
|
|
||||||
|
|
||||||
1. **Choose the appropriate state**: Register callbacks at the earliest
|
|
||||||
state where all dependencies are guaranteed to be initialized, but no
|
|
||||||
earlier. Check the state descriptions and the functions called by
|
|
||||||
each state function (`bs_*`) in `hardwaremain.c`.
|
|
||||||
|
|
||||||
2. **Keep callbacks focused**: Each callback should perform a specific,
|
|
||||||
related task and avoid complex operations that might significantly
|
|
||||||
delay the boot process.
|
|
||||||
|
|
||||||
3. **Consider dependencies carefully**: Ensure any hardware, data
|
|
||||||
structures, or other resources your callback needs are available and
|
|
||||||
initialized at the chosen state and sequence (`BS_ON_ENTRY` vs.
|
|
||||||
`BS_ON_EXIT`).
|
|
||||||
|
|
||||||
4. **Do not rely on callback order**: Remember that the execution order
|
|
||||||
of callbacks within the same state and sequence is not guaranteed.
|
|
||||||
Callbacks should be self-contained and not depend on side effects from
|
|
||||||
other callbacks that might run before or after them in the same phase.
|
|
||||||
|
|
||||||
5. **Use blocking sparingly**: The blocking mechanism is powerful for
|
|
||||||
synchronization but can complicate the boot flow and make debugging
|
|
||||||
harder if overused. Always ensure a corresponding `boot_state_unblock`
|
|
||||||
call will eventually run.
|
|
||||||
|
|
||||||
6. **Leverage compile-time registration**: Prefer using
|
|
||||||
`BOOT_STATE_INIT_ENTRY` for callbacks whenever possible. It makes the
|
|
||||||
registration explicit and easier to find. Runtime registration is
|
|
||||||
necessary only when the need for the callback is determined dynamically.
|
|
||||||
|
|
||||||
7. **Debug with timestamps and `DEBUG_BOOT_STATE`**: Use the timestamp API
|
|
||||||
(`timestamp_add_now()`) and enable `DEBUG_BOOT_STATE` to measure
|
|
||||||
callback execution time, identify bottlenecks, and understand the
|
|
||||||
flow during development.
|
|
||||||
|
|
||||||
8. **Document state-specific behavior**: When adding callbacks, add
|
|
||||||
comments explaining why they are placed in a particular state and
|
|
||||||
sequence.
|
|
||||||
|
|
||||||
9. **Be careful with late states**: Avoid registering non-essential
|
|
||||||
callbacks in `BS_PAYLOAD_BOOT` or `BS_OS_RESUME`. Callbacks on
|
|
||||||
`BS_ON_EXIT` for these states are disallowed by compile-time asserts,
|
|
||||||
as coreboot is about to transfer control.
|
|
||||||
|
|
||||||
|
|
||||||
## Related Documentation
|
|
||||||
|
|
||||||
- [Boot Stages in coreboot](https://doc.coreboot.org/getting_started/architecture.html):
|
|
||||||
Overview of all coreboot boot stages.
|
|
||||||
|
|
||||||
|
|
||||||
## References
|
|
||||||
|
|
||||||
- `src/include/bootstate.h`: Public API definitions (callbacks, enums,
|
|
||||||
scheduling/blocking functions, static registration macro).
|
|
||||||
- `src/lib/hardwaremain.c`: Internal implementation (state machine driver,
|
|
||||||
state definitions, state functions).
|
|
||||||
- `src/ec/google/wilco/chip.c`: Example of bootstate callback usage.
|
|
||||||
- `src/mainboard/prodrive/hermes/mainboard.c`: Examples of mainboard-specific
|
|
||||||
bootstate callbacks.
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
||||||
# Relocatable Modules (rmodules)
|
|
||||||
|
|
||||||
Relocatable modules are currently only used on x86. Relocatable
|
|
||||||
modules are executables. Exectuables which can be executed anywhere in
|
|
||||||
memory. Anywhere means that the module does not need to be executed
|
|
||||||
at a defined memory address which is known at build/link time. For
|
|
||||||
coreboot stages like bootblock and romstage it is known at build
|
|
||||||
time at which addresses they are executed. For some exectuables it
|
|
||||||
is however not known at which specific address they are executed in
|
|
||||||
runtime (for example postcar and ramstage). Relocateable modules
|
|
||||||
usually allocate the space for the modules just before they are
|
|
||||||
supposed to be executed. After enough space is allocated, CBMEM will
|
|
||||||
return the location of the allocated space. Now the relocation can be
|
|
||||||
done by fixing up all relocation entries in the relocatable module
|
|
||||||
based on the location of the binary (which was returned by CBMEM
|
|
||||||
at runtime).
|
|
||||||
|
|
||||||
## Implementation Details
|
|
||||||
|
|
||||||
### Build Time
|
|
||||||
|
|
||||||
At build time the rmodtool (util/cbfstool/rmodtool.c) is used to
|
|
||||||
create relocatable modules. The rmodtool basically takes an ELF
|
|
||||||
file as an input and writes an ELF as output. It basically does
|
|
||||||
a simple conversion from one ELF file to another slighty changed
|
|
||||||
ELF file. First the tool makes sure that the ELF file fits a few
|
|
||||||
requirements. For example there can only be one segment (loadable
|
|
||||||
program header) in the input ELF file. After that it goes through
|
|
||||||
the ELF relocation table and takes any entry that applies to the one
|
|
||||||
segment we want to load at runtime. The rmodtool will then write all
|
|
||||||
these relocation entires in a new ELF section called ".reloc". After
|
|
||||||
that the ELF relocation table will be cleared.
|
|
||||||
|
|
||||||
One can split the rmodules in two different kinds:
|
|
||||||
1. coreboot stages (postcar, ramstage)
|
|
||||||
2. simple binaries (smm, smmstub, sipi\_vector)
|
|
||||||
|
|
||||||
There is one important difference in how they are handled:
|
|
||||||
The simple binaries are compiled into rmodules the same as coreboot
|
|
||||||
stages are, but the simple binaries are always directly linked to a
|
|
||||||
stage. Since rmodules are ELF files as well, we can easily link them
|
|
||||||
to the stages in which we need them (usually postcar or ramstage).
|
|
||||||
So they are not really separate modules anymore, but still retain
|
|
||||||
the ability to accept rmodule\_parameters.
|
|
||||||
Since the simple binaries are usually very small, linking them directly
|
|
||||||
into the stage (e.g. ramstage or postcar) avoids having to fetch them
|
|
||||||
from CBFS and running all that code to fetch a few hundred bytes of
|
|
||||||
code. So the build system handles them as follows:
|
|
||||||
1. create rmodule (which is an ELF file) from source files
|
|
||||||
2. remove all the ELF headers and sections that are not loadable using
|
|
||||||
`objcopy -O binary`
|
|
||||||
3. from this, create an object file, which usually has the self invented
|
|
||||||
.manual file extension, which can be linked to the appropriate stage
|
|
||||||
4. add the generated .manual file as "source" file to the stage we want
|
|
||||||
to link it to
|
|
||||||
|
|
||||||
In the end the ELF files will have three different ELF sections,
|
|
||||||
which are all created by the rmodtool.
|
|
||||||
1. relocation header (.header)
|
|
||||||
2. program (.program)
|
|
||||||
3. relocation entries (.relocs)
|
|
||||||
|
|
||||||
### Runtime
|
|
||||||
|
|
||||||
Either rmodule\_load (lib/rmodule.c) is used directly or through the
|
|
||||||
rmodule\_stage\_load (lib/rmodule.c) wrapper. It is used to load the
|
|
||||||
stages (postcar and ramstage) or small programs like (sipi\_vector,
|
|
||||||
smm, smmstub) into memory before jumping to them. In the case of a
|
|
||||||
coreboot stage, CBMEM is used to allocate space for the stage in memory
|
|
||||||
via the rmodule\_cbfs\_allocater (lib/rmodule.c). At this point the
|
|
||||||
location of the stage in memory is known and all relocation (address
|
|
||||||
fixups) need to be done now. This is basically just a simple loop that
|
|
||||||
goes through each relocation entry. Each relocation entry is just an
|
|
||||||
address pointing to a location that needs relocation. The relocation
|
|
||||||
itself is just a simple addition, that adds an offset from where the
|
|
||||||
image was "supposed" to be at link time, to where it is now relocated.
|
|
||||||
|
|
||||||
### module\_parameters
|
|
||||||
|
|
||||||
module\_parameters is a section inside the rmodule ELF file. Its
|
|
||||||
basically a way to pass runtime information to an rmodule
|
|
||||||
before jumping to it. The caller will use rmodule\_parameters()
|
|
||||||
(lib/rmodule.c) to get the runtime address of the module\_parameters
|
|
||||||
and the callee (the rmodule itself) usually appends the section to
|
|
||||||
specific types via compiler attributes. For example:
|
|
||||||
```
|
|
||||||
static const
|
|
||||||
volatile __attribute((aligned(4), __section__(".module_parameters")))
|
|
||||||
struct smm_runtime smm_runtime;
|
|
||||||
```
|
|
||||||
|
|
||||||
## x86 why rmodules
|
|
||||||
//TODO
|
|
||||||
x86: postcar and ramstage cannot conflict with payload regarding
|
|
||||||
memory placement. Therefore payload location is usually fixed and
|
|
||||||
postcar/ramstage can be placed at a location in memory that is
|
|
||||||
figured out at runtime.
|
|
||||||
|
|
@ -1,910 +0,0 @@
|
||||||
# coreboot Timers, Stopwatch, Delays, and Associated Callbacks
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
|
|
||||||
coreboot provides several mechanisms for handling time, including
|
|
||||||
high-precision stopwatches for profiling, simple delay functions for
|
|
||||||
hardware timing, and a monotonic timer system that forms the foundation
|
|
||||||
for these features. It also supports scheduling timer callbacks for
|
|
||||||
deferred execution. These tools are crucial for performance
|
|
||||||
optimization, debugging, ensuring proper hardware timing, and managing
|
|
||||||
asynchronous events during the boot process.
|
|
||||||
|
|
||||||
This document describes the core monotonic timer, the delay functions
|
|
||||||
(`udelay`, `mdelay`, `delay`), the stopwatch API (`struct stopwatch`),
|
|
||||||
and the timer callback mechanism.
|
|
||||||
|
|
||||||
|
|
||||||
## Architecture Overview
|
|
||||||
|
|
||||||
The timing facilities are layered:
|
|
||||||
|
|
||||||
- **Platform Timer:** Hardware-specific implementations provide a raw
|
|
||||||
time source (e.g., LAPIC timer, Time Base register). These are often
|
|
||||||
abstracted by `timer_monotonic_get()`.
|
|
||||||
- **Monotonic Timer:** (`src/include/timer.h`, `src/lib/timer.c`)
|
|
||||||
Provides a consistent time source (`struct mono_time`) counting
|
|
||||||
microseconds since timer initialization. Requires
|
|
||||||
`CONFIG(HAVE_MONOTONIC_TIMER)`.
|
|
||||||
- **Delay Functions:** (`src/include/delay.h`, `src/lib/delay.c`,
|
|
||||||
`src/lib/timer.c`) Simple blocking delays (`udelay`, `mdelay`,
|
|
||||||
`delay`). The generic `udelay` uses the stopwatch API if yielding via
|
|
||||||
`thread_yield_microseconds()` is not performed.
|
|
||||||
- **Stopwatch API:** (`src/include/timer.h`) A lightweight wrapper
|
|
||||||
around the monotonic timer for measuring durations and handling
|
|
||||||
timeouts (`struct stopwatch`,`wait_us`,`wait_ms`).
|
|
||||||
- **Timer Callbacks:** (`src/include/timer.h`) Allows scheduling
|
|
||||||
functions to be called after a specified delay
|
|
||||||
(`struct timeout_callback`, `timer_sched_callback()`, `timers_run()`).
|
|
||||||
|
|
||||||
These APIs are generally designed to be thread-safe and usable across
|
|
||||||
different boot stages.
|
|
||||||
|
|
||||||
|
|
||||||
## Core Monotonic Timer
|
|
||||||
|
|
||||||
The foundation is the monotonic timer, enabled by
|
|
||||||
`CONFIG(HAVE_MONOTONIC_TIMER)`. It provides a time source that
|
|
||||||
continuously increases from an arbitrary starting point (usually near
|
|
||||||
timer initialization).
|
|
||||||
|
|
||||||
### Data Structures
|
|
||||||
|
|
||||||
#### struct mono_time
|
|
||||||
|
|
||||||
```c
|
|
||||||
struct mono_time {
|
|
||||||
uint64_t microseconds; // Time in microseconds since timer init
|
|
||||||
};
|
|
||||||
```
|
|
||||||
Represents a point in monotonic time. Direct field access outside core
|
|
||||||
timer code is discouraged; use helper functions.
|
|
||||||
|
|
||||||
### API Functions
|
|
||||||
|
|
||||||
#### timer_monotonic_get
|
|
||||||
|
|
||||||
```c
|
|
||||||
void timer_monotonic_get(struct mono_time *mt);
|
|
||||||
```
|
|
||||||
Retrieves the current monotonic time.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `mt`: Pointer to a `struct mono_time` to store the current time.
|
|
||||||
|
|
||||||
**Preconditions:**
|
|
||||||
- `CONFIG(HAVE_MONOTONIC_TIMER)` must be enabled.
|
|
||||||
- The underlying platform timer must be functional. Platform
|
|
||||||
implementations may require an `init_timer()` call.
|
|
||||||
|
|
||||||
**Postconditions:**
|
|
||||||
- `mt` contains the current monotonic time in microseconds.
|
|
||||||
|
|
||||||
**Note:** If `CONFIG(HAVE_MONOTONIC_TIMER)` is *not* enabled, functions
|
|
||||||
relying on it (like stopwatch functions) will generally fall back to
|
|
||||||
basic behavior (e.g., returning 0 durations, immediate expiration
|
|
||||||
checks).
|
|
||||||
|
|
||||||
#### init_timer
|
|
||||||
|
|
||||||
```c
|
|
||||||
void init_timer(void);
|
|
||||||
```
|
|
||||||
|
|
||||||
Platform-specific timer initialization. The generic version in
|
|
||||||
`src/lib/timer.c` is a weak empty function
|
|
||||||
`__weak void init_timer(void) { /* do nothing */ }`. Platforms needing
|
|
||||||
explicit timer setup (e.g., configuring frequency, enabling the
|
|
||||||
counter) must provide their own strong implementation. Check platform
|
|
||||||
code (`src/cpu/`, `src/soc/`) for details.
|
|
||||||
|
|
||||||
#### `mono_time` Helper Functions
|
|
||||||
|
|
||||||
`src/include/timer.h` also provides several inline helper functions for
|
|
||||||
manipulating `struct mono_time` values:
|
|
||||||
- `mono_time_set_usecs()`, `mono_time_set_msecs()`: Set time.
|
|
||||||
- `mono_time_add_usecs()`, `mono_time_add_msecs()`: Add duration.
|
|
||||||
- `mono_time_cmp()`: Compare two times.
|
|
||||||
- `mono_time_after()`, `mono_time_before()`: Check time ordering.
|
|
||||||
- `mono_time_diff_microseconds()`: Calculate difference between two
|
|
||||||
times.
|
|
||||||
|
|
||||||
Refer to `src/include/timer.h` for their exact definitions.
|
|
||||||
|
|
||||||
|
|
||||||
## Delay Functions
|
|
||||||
|
|
||||||
coreboot provides simple functions for introducing delays.
|
|
||||||
|
|
||||||
### udelay
|
|
||||||
|
|
||||||
```c
|
|
||||||
void udelay(unsigned int usecs);
|
|
||||||
```
|
|
||||||
Delays execution for *at least* the specified number of microseconds.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `usecs`: Number of microseconds to delay.
|
|
||||||
|
|
||||||
**Implementation Notes:**
|
|
||||||
- The generic implementation in `src/lib/timer.c` first attempts to
|
|
||||||
yield using `thread_yield_microseconds()` if `CONFIG(HAS_THREADS)` is
|
|
||||||
enabled. If yielding handles the required delay (function returns 0),
|
|
||||||
`udelay` returns immediately, allowing other threads to run.
|
|
||||||
- If `thread_yield_microseconds()` does not handle the delay (returns
|
|
||||||
non-zero), or if threading is disabled, the generic `udelay` falls
|
|
||||||
back to a busy-wait using the stopwatch API
|
|
||||||
(`stopwatch_init_usecs_expire()` and
|
|
||||||
`stopwatch_wait_until_expired()`).
|
|
||||||
- Architecture-specific implementations (e.g., in `src/arch/`) may
|
|
||||||
override the generic one for better precision or efficiency.
|
|
||||||
- Adds 1 microsecond internally to ensure the delay is *at least* the
|
|
||||||
requested duration.
|
|
||||||
|
|
||||||
**Preconditions:**
|
|
||||||
- If relying on the stopwatch fallback,
|
|
||||||
`CONFIG(HAVE_MONOTONIC_TIMER)` is needed.
|
|
||||||
- Underlying timer (if used) must be initialized (potentially via a
|
|
||||||
platform `init_timer()`).
|
|
||||||
- The delay value should be reasonable (overly large values might cause
|
|
||||||
issues or unexpected behavior depending on the implementation).
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
```c
|
|
||||||
#include <delay.h>
|
|
||||||
|
|
||||||
// Wait for 100 microseconds
|
|
||||||
udelay(100);
|
|
||||||
```
|
|
||||||
|
|
||||||
### mdelay
|
|
||||||
|
|
||||||
```c
|
|
||||||
void mdelay(unsigned int msecs);
|
|
||||||
```
|
|
||||||
Delays execution for *at least* the specified number of milliseconds.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `msecs`: Number of milliseconds to delay.
|
|
||||||
|
|
||||||
**Implementation Notes:**
|
|
||||||
- The generic implementation in `src/lib/delay.c` simply calls
|
|
||||||
`udelay(1000)` in a loop `msecs` times.
|
|
||||||
- Therefore, it inherits the behavior of `udelay`, including the attempt
|
|
||||||
to yield first if `udelay` supports it.
|
|
||||||
|
|
||||||
**Preconditions:**
|
|
||||||
- Same as `udelay`.
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
```c
|
|
||||||
#include <delay.h>
|
|
||||||
|
|
||||||
// Wait for 50 milliseconds
|
|
||||||
mdelay(50);
|
|
||||||
```
|
|
||||||
|
|
||||||
### delay
|
|
||||||
|
|
||||||
```c
|
|
||||||
void delay(unsigned int secs);
|
|
||||||
```
|
|
||||||
Delays execution for *at least* the specified number of seconds.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `secs`: Number of seconds to delay.
|
|
||||||
|
|
||||||
**Implementation Notes:**
|
|
||||||
- The generic implementation in `src/lib/delay.c` simply calls
|
|
||||||
`mdelay(1000)` in a loop `secs` times.
|
|
||||||
- Inherits the behavior of `mdelay` and `udelay`.
|
|
||||||
|
|
||||||
**Preconditions:**
|
|
||||||
- Same as `udelay`.
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
```c
|
|
||||||
#include <delay.h>
|
|
||||||
|
|
||||||
// Wait for 2 seconds
|
|
||||||
delay(2);
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Stopwatch API
|
|
||||||
|
|
||||||
The stopwatch API provides a convenient way to measure time durations
|
|
||||||
and implement timeouts based on the monotonic timer.
|
|
||||||
|
|
||||||
### Data Structures
|
|
||||||
|
|
||||||
#### struct stopwatch
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h> // For struct stopwatch and struct mono_time
|
|
||||||
|
|
||||||
struct stopwatch {
|
|
||||||
struct mono_time start; // Time when stopwatch was started or initialized
|
|
||||||
struct mono_time current; // Time when stopwatch was last ticked
|
|
||||||
struct mono_time expires; // Expiration time for timeout operations
|
|
||||||
};
|
|
||||||
```
|
|
||||||
Holds the state for a stopwatch instance.
|
|
||||||
|
|
||||||
### API Functions
|
|
||||||
|
|
||||||
#### Initialization Functions
|
|
||||||
|
|
||||||
##### stopwatch_init
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
|
|
||||||
static inline void stopwatch_init(struct stopwatch *sw);
|
|
||||||
```
|
|
||||||
Initializes a stopwatch structure. `start`, `current`, and `expires` are
|
|
||||||
all set to the current monotonic time. Use this when you only need to
|
|
||||||
measure elapsed duration from initialization.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `sw`: Pointer to the stopwatch structure to initialize.
|
|
||||||
|
|
||||||
**Preconditions:**
|
|
||||||
- `sw` must point to valid memory.
|
|
||||||
- `CONFIG(HAVE_MONOTONIC_TIMER)` should be enabled for meaningful
|
|
||||||
timing.
|
|
||||||
|
|
||||||
**Postconditions:**
|
|
||||||
- The stopwatch is initialized.
|
|
||||||
|
|
||||||
|
|
||||||
##### stopwatch_init_usecs_expire
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
|
|
||||||
static inline void stopwatch_init_usecs_expire(struct stopwatch *sw, uint64_t us);
|
|
||||||
```
|
|
||||||
Initializes a stopwatch and sets an expiration time `us` microseconds
|
|
||||||
from now.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `sw`: Pointer to the stopwatch structure.
|
|
||||||
- `us`: Timeout duration in microseconds.
|
|
||||||
|
|
||||||
**Preconditions:**
|
|
||||||
- `sw` must point to valid memory.
|
|
||||||
- `CONFIG(HAVE_MONOTONIC_TIMER)` should be enabled.
|
|
||||||
|
|
||||||
**Postconditions:**
|
|
||||||
- The stopwatch is initialized, and `expires` is set `us` microseconds
|
|
||||||
after `start`.
|
|
||||||
|
|
||||||
|
|
||||||
##### stopwatch_init_msecs_expire
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
|
|
||||||
static inline void stopwatch_init_msecs_expire(struct stopwatch *sw, uint64_t ms);
|
|
||||||
```
|
|
||||||
Initializes a stopwatch and sets an expiration time `ms` milliseconds
|
|
||||||
from now.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `sw`: Pointer to the stopwatch structure.
|
|
||||||
- `ms`: Timeout duration in milliseconds.
|
|
||||||
|
|
||||||
**Preconditions:**
|
|
||||||
- `sw` must point to valid memory.
|
|
||||||
- `CONFIG(HAVE_MONOTONIC_TIMER)` should be enabled.
|
|
||||||
|
|
||||||
**Postconditions:**
|
|
||||||
- The stopwatch is initialized, and `expires` is set `ms` milliseconds
|
|
||||||
after `start`.
|
|
||||||
|
|
||||||
|
|
||||||
#### Time Measurement Functions
|
|
||||||
|
|
||||||
##### stopwatch_tick
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
|
|
||||||
static inline void stopwatch_tick(struct stopwatch *sw);
|
|
||||||
```
|
|
||||||
Updates the `current` time field in the stopwatch structure to the
|
|
||||||
current monotonic time. This is often called implicitly by other
|
|
||||||
stopwatch functions like `stopwatch_expired()` and
|
|
||||||
`stopwatch_duration_usecs()`.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `sw`: Pointer to the stopwatch structure.
|
|
||||||
|
|
||||||
**Preconditions:**
|
|
||||||
- The stopwatch must be initialized.
|
|
||||||
- `CONFIG(HAVE_MONOTONIC_TIMER)` should be enabled.
|
|
||||||
|
|
||||||
|
|
||||||
##### stopwatch_expired
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
|
|
||||||
static inline int stopwatch_expired(struct stopwatch *sw);
|
|
||||||
```
|
|
||||||
Checks if the stopwatch's expiration time (`expires`) has passed. It
|
|
||||||
implicitly calls `stopwatch_tick()` to get the current time for
|
|
||||||
comparison.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `sw`: Pointer to the stopwatch structure.
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
- Non-zero (true) if `current` time >= `expires` time.
|
|
||||||
- Zero (false) otherwise.
|
|
||||||
|
|
||||||
**Preconditions:**
|
|
||||||
- The stopwatch must be initialized (preferably with an expiration
|
|
||||||
time).
|
|
||||||
- `CONFIG(HAVE_MONOTONIC_TIMER)` should be enabled.
|
|
||||||
|
|
||||||
|
|
||||||
##### stopwatch_wait_until_expired
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
|
|
||||||
static inline void stopwatch_wait_until_expired(struct stopwatch *sw);
|
|
||||||
```
|
|
||||||
Blocks (busy-waits) until the stopwatch expires by repeatedly calling
|
|
||||||
`stopwatch_expired()`.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `sw`: Pointer to the stopwatch structure.
|
|
||||||
|
|
||||||
**Preconditions:**
|
|
||||||
- The stopwatch must be initialized with an expiration time.
|
|
||||||
- `CONFIG(HAVE_MONOTONIC_TIMER)` should be enabled.
|
|
||||||
|
|
||||||
**Postconditions:**
|
|
||||||
- The function returns only after the stopwatch has expired.
|
|
||||||
|
|
||||||
|
|
||||||
#### Duration Measurement Functions
|
|
||||||
|
|
||||||
##### stopwatch_duration_usecs
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
|
|
||||||
static inline int64_t stopwatch_duration_usecs(struct stopwatch *sw);
|
|
||||||
```
|
|
||||||
Returns the elapsed time in microseconds between `start` and `current`.
|
|
||||||
If `current` hasn't been updated since `stopwatch_init`, it implicitly
|
|
||||||
calls `stopwatch_tick()` first.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `sw`: Pointer to the stopwatch structure.
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
- Elapsed time in microseconds (`current` - `start`).
|
|
||||||
|
|
||||||
**Preconditions:**
|
|
||||||
- The stopwatch must be initialized.
|
|
||||||
- `CONFIG(HAVE_MONOTONIC_TIMER)` should be enabled for a meaningful
|
|
||||||
duration.
|
|
||||||
|
|
||||||
|
|
||||||
##### stopwatch_duration_msecs
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
|
|
||||||
static inline int64_t stopwatch_duration_msecs(struct stopwatch *sw);
|
|
||||||
```
|
|
||||||
Returns the elapsed time in milliseconds since the stopwatch was
|
|
||||||
started. It calls `stopwatch_duration_usecs()` and divides by 1000.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `sw`: Pointer to the stopwatch structure.
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
- Elapsed time in milliseconds.
|
|
||||||
|
|
||||||
**Preconditions:**
|
|
||||||
- The stopwatch must be initialized.
|
|
||||||
- `CONFIG(HAVE_MONOTONIC_TIMER)` should be enabled.
|
|
||||||
|
|
||||||
|
|
||||||
### Utility Macros
|
|
||||||
|
|
||||||
These macros combine stopwatch initialization and expiration checking with
|
|
||||||
a user-provided condition.
|
|
||||||
|
|
||||||
#### wait_us
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
|
|
||||||
#define wait_us(timeout_us, condition) ...
|
|
||||||
```
|
|
||||||
Waits until a condition becomes true or a timeout elapses, whichever
|
|
||||||
comes first. Internally uses a `struct stopwatch`.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `timeout_us`: Timeout duration in microseconds.
|
|
||||||
- `condition`: A C expression that evaluates to true or false. The loop
|
|
||||||
continues as long as the condition is false and the timeout has not
|
|
||||||
expired.
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
- 0: If the condition was still false when the timeout expired.
|
|
||||||
- >0: If the condition became true before the timeout. The return value
|
|
||||||
is the approximate number of microseconds waited (at least 1).
|
|
||||||
|
|
||||||
**Preconditions:**
|
|
||||||
- `CONFIG(HAVE_MONOTONIC_TIMER)` should be enabled.
|
|
||||||
|
|
||||||
|
|
||||||
#### wait_ms
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
|
|
||||||
#define wait_ms(timeout_ms, condition) ...
|
|
||||||
```
|
|
||||||
Similar to `wait_us`, but the timeout is specified in milliseconds.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `timeout_ms`: Timeout duration in milliseconds.
|
|
||||||
- `condition`: C expression to wait for.
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
- 0: If the condition was still false after the timeout.
|
|
||||||
- >0: If the condition became true before the timeout. The return value
|
|
||||||
is the approximate number of milliseconds waited (rounded up, at
|
|
||||||
least 1).
|
|
||||||
|
|
||||||
**Preconditions:**
|
|
||||||
- `CONFIG(HAVE_MONOTONIC_TIMER)` should be enabled.
|
|
||||||
|
|
||||||
|
|
||||||
## Key differences between `mdelay` and `wait_ms`
|
|
||||||
|
|
||||||
While both can be used to wait, they serve different purposes:
|
|
||||||
|
|
||||||
### Purpose and Use Case
|
|
||||||
|
|
||||||
- `mdelay`: Provides an *unconditional* delay for a fixed duration. The
|
|
||||||
generic implementation attempts to yield to other threads first (if
|
|
||||||
`CONFIG(HAS_THREADS)` is enabled via `udelay`), but it always waits
|
|
||||||
for (at least) the specified time, potentially using a busy-wait if
|
|
||||||
yielding doesn't occur. Primarily used for hardware timing
|
|
||||||
requirements or pacing operations.
|
|
||||||
|
|
||||||
- `wait_ms`: Provides a *conditional* wait. It waits for a specific C
|
|
||||||
expression (`condition`) to become true, but *only up to* a maximum
|
|
||||||
timeout duration. Used when polling for a status change or event, with
|
|
||||||
a safeguard against waiting indefinitely.
|
|
||||||
|
|
||||||
### When to Use Which
|
|
||||||
|
|
||||||
#### Use `mdelay` when:
|
|
||||||
|
|
||||||
- You need a guaranteed minimum delay (e.g., waiting for hardware to
|
|
||||||
settle after a register write).
|
|
||||||
- You are implementing a hardware initialization sequence with specific
|
|
||||||
timing requirements between steps.
|
|
||||||
- You want a simple pause, potentially allowing other threads to run if
|
|
||||||
the underlying `udelay` yields.
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
```c
|
|
||||||
#include <delay.h>
|
|
||||||
#include <arch/io.h> // For write_reg hypothetical function
|
|
||||||
|
|
||||||
// Initialize hardware with specific timing requirements
|
|
||||||
write_reg(REG_A, value);
|
|
||||||
mdelay(10); // Must wait (at least) 10ms after writing REG_A
|
|
||||||
write_reg(REG_B, another_value);
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Use `wait_ms` when:
|
|
||||||
|
|
||||||
- You are waiting for a hardware status bit to change or a condition to
|
|
||||||
become true.
|
|
||||||
- You need to implement a timeout for an operation that might fail or
|
|
||||||
take too long.
|
|
||||||
- You want to know approximately how long you waited for the condition
|
|
||||||
to become true (via the return value).
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
#include <console/console.h>
|
|
||||||
#include <arch/io.h> // For read_reg hypothetical function
|
|
||||||
|
|
||||||
// Wait for hardware to become ready, but not forever
|
|
||||||
#define STATUS_REG 0x100
|
|
||||||
#define READY_BIT (1 << 0)
|
|
||||||
int64_t waited_ms = wait_ms(100, (read_reg(STATUS_REG) & READY_BIT));
|
|
||||||
|
|
||||||
if (waited_ms > 0) {
|
|
||||||
printk(BIOS_INFO, "Hardware ready after ~%lld ms\n", waited_ms);
|
|
||||||
} else {
|
|
||||||
printk(BIOS_ERR, "Timeout: Hardware failed to become ready within 100 ms\n");
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Performance Considerations
|
|
||||||
|
|
||||||
- `mdelay`: Generally simpler if the underlying `udelay` performs a
|
|
||||||
busy-wait. If it yields (`thread_yield_microseconds`), overhead depends
|
|
||||||
on the scheduler. Always waits for the full duration (approximately).
|
|
||||||
- `wait_ms`: Involves repeated condition checking and stopwatch
|
|
||||||
management (`stopwatch_expired`, which calls `timer_monotonic_get`),
|
|
||||||
adding overhead within the loop. However, it can return early if the
|
|
||||||
condition becomes true, potentially saving time compared to a fixed
|
|
||||||
`mdelay`.
|
|
||||||
|
|
||||||
### Error Handling / Feedback
|
|
||||||
|
|
||||||
- `mdelay`: Provides no feedback. It simply waits.
|
|
||||||
- `wait_ms`: Returns whether the condition was met within the timeout
|
|
||||||
and provides the approximate wait time if successful. This allows for
|
|
||||||
explicit timeout handling.
|
|
||||||
|
|
||||||
### Summary
|
|
||||||
|
|
||||||
Use `mdelay` for fixed, unconditional delays, potentially allowing
|
|
||||||
thread yielding. Use `wait_ms` for conditional waits with a timeout and
|
|
||||||
feedback on success or failure. Choose based on whether you need to poll
|
|
||||||
for a condition or simply need to pause execution.
|
|
||||||
|
|
||||||
|
|
||||||
## Timer Callbacks
|
|
||||||
|
|
||||||
coreboot provides a mechanism to schedule functions (callbacks) to be
|
|
||||||
executed after a certain time has elapsed. This requires
|
|
||||||
`CONFIG(TIMER_QUEUE)`.
|
|
||||||
|
|
||||||
### Data Structures
|
|
||||||
|
|
||||||
#### struct timeout_callback
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
|
|
||||||
struct timeout_callback {
|
|
||||||
void *priv; // Private data for the callback
|
|
||||||
void (*callback)(struct timeout_callback *tocb); // Function to call
|
|
||||||
/* Internal use by timer library: */
|
|
||||||
struct mono_time expiration; // Calculated expiration time
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Represents a scheduled callback. The user initializes `priv` and
|
|
||||||
`callback`.
|
|
||||||
|
|
||||||
### API Functions
|
|
||||||
|
|
||||||
#### timer_sched_callback
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
|
|
||||||
int timer_sched_callback(struct timeout_callback *tocb, uint64_t us);
|
|
||||||
```
|
|
||||||
Schedules a callback function to run after a specified delay.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `tocb`: Pointer to a `struct timeout_callback`. The `priv` and
|
|
||||||
`callback` fields must be set by the caller. The structure must
|
|
||||||
persist until the callback runs or is canceled (cancellation not
|
|
||||||
directly supported by API).
|
|
||||||
- `us`: Delay in microseconds from the time of this call until the
|
|
||||||
callback should run.
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
- 0: Success.
|
|
||||||
- <0: Error (e.g., timer queue full, invalid arguments).
|
|
||||||
|
|
||||||
**Preconditions:**
|
|
||||||
- `CONFIG(TIMER_QUEUE)` and `CONFIG(HAVE_MONOTONIC_TIMER)` must be
|
|
||||||
enabled.
|
|
||||||
- `tocb` must point to a valid structure with `callback` assigned.
|
|
||||||
|
|
||||||
**Postconditions:**
|
|
||||||
- The callback is added to a queue, to be executed when `timers_run()`
|
|
||||||
is called after the expiration time.
|
|
||||||
|
|
||||||
|
|
||||||
#### timers_run
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
|
|
||||||
int timers_run(void);
|
|
||||||
```
|
|
||||||
|
|
||||||
Checks the timer callback queue and executes any callbacks whose
|
|
||||||
expiration time has passed. This function needs to be called
|
|
||||||
periodically from the main execution flow (e.g., in a boot state loop
|
|
||||||
or idle task) for callbacks to be processed.
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
- 1: If callbacks were run or are still pending in the queue.
|
|
||||||
- 0: If the queue is empty and no callbacks were run.
|
|
||||||
|
|
||||||
**Preconditions:**
|
|
||||||
- `CONFIG(TIMER_QUEUE)` and `CONFIG(HAVE_MONOTONIC_TIMER)` must be
|
|
||||||
enabled.
|
|
||||||
|
|
||||||
**Usage:**
|
|
||||||
Typically called in loops where deferred work might need processing:
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
|
|
||||||
// Example main loop structure
|
|
||||||
while (some_condition) {
|
|
||||||
// ... do other work ...
|
|
||||||
|
|
||||||
// Process any expired timer callbacks
|
|
||||||
timers_run();
|
|
||||||
|
|
||||||
// ... potentially yield or sleep ...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Usage Examples
|
|
||||||
|
|
||||||
### Basic Timing Measurement Example
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
#include <console/console.h>
|
|
||||||
|
|
||||||
struct stopwatch sw;
|
|
||||||
stopwatch_init(&sw);
|
|
||||||
|
|
||||||
// ---> Code section to measure start
|
|
||||||
// ... perform some operations ...
|
|
||||||
// ---> Code section to measure end
|
|
||||||
|
|
||||||
// stopwatch_duration_usecs implicitly ticks the stopwatch if needed
|
|
||||||
int64_t duration_us = stopwatch_duration_usecs(&sw);
|
|
||||||
printk(BIOS_INFO, "Operation took %lld microseconds\n", duration_us);
|
|
||||||
|
|
||||||
// Or in milliseconds
|
|
||||||
int64_t duration_ms = stopwatch_duration_msecs(&sw);
|
|
||||||
printk(BIOS_INFO, "Operation took %lld milliseconds\n", duration_ms);
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Timeout Operation (Polling) Example
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
#include <console/console.h>
|
|
||||||
#include <stdint.h> // For uint8_t example
|
|
||||||
|
|
||||||
// Hypothetical hardware status check
|
|
||||||
extern uint8_t check_hardware_status(void);
|
|
||||||
#define HW_READY (1 << 0)
|
|
||||||
|
|
||||||
struct stopwatch sw;
|
|
||||||
// Initialize stopwatch with a 100 millisecond timeout
|
|
||||||
stopwatch_init_msecs_expire(&sw, 100);
|
|
||||||
|
|
||||||
uint8_t status = 0;
|
|
||||||
while (!(status & HW_READY)) {
|
|
||||||
status = check_hardware_status();
|
|
||||||
|
|
||||||
if (stopwatch_expired(&sw)) {
|
|
||||||
printk(BIOS_ERR, "Operation timed out waiting for HW_READY\n");
|
|
||||||
// Handle timeout error...
|
|
||||||
status = 0; // Indicate failure perhaps
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Optional: Add a small delay here to avoid busy-spinning the CPU excessively
|
|
||||||
// udelay(10); // e.g., wait 10us between checks
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status & HW_READY) {
|
|
||||||
printk(BIOS_DEBUG, "Hardware became ready.\n");
|
|
||||||
// Continue with operation...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Waiting for a Condition (Using `wait_ms`) Example
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
#include <console/console.h>
|
|
||||||
#include <stdint.h> // For uint8_t example
|
|
||||||
|
|
||||||
// Hypothetical hardware status check
|
|
||||||
extern uint8_t check_hardware_status(void);
|
|
||||||
#define HW_READY (1 << 0)
|
|
||||||
|
|
||||||
// Wait up to 100ms for the HW_READY bit
|
|
||||||
int64_t waited_ms = wait_ms(100, (check_hardware_status() & HW_READY));
|
|
||||||
|
|
||||||
if (waited_ms > 0) {
|
|
||||||
printk(BIOS_INFO, "Condition met: HW_READY asserted after ~%lld ms\n", waited_ms);
|
|
||||||
// Continue...
|
|
||||||
} else {
|
|
||||||
printk(BIOS_ERR, "Timeout: HW_READY not asserted within 100 ms\n");
|
|
||||||
// Handle timeout error...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Scheduling a Timer Callback Example
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timer.h>
|
|
||||||
#include <console/console.h>
|
|
||||||
|
|
||||||
// Data structure for our callback context
|
|
||||||
struct my_callback_data {
|
|
||||||
int counter;
|
|
||||||
const char *message;
|
|
||||||
};
|
|
||||||
|
|
||||||
// The callback function
|
|
||||||
static void my_callback_handler(struct timeout_callback *tocb)
|
|
||||||
{
|
|
||||||
struct my_callback_data *data = tocb->priv;
|
|
||||||
printk(BIOS_INFO, "Callback executed! Message: %s, Counter: %d\n",
|
|
||||||
data->message, data->counter);
|
|
||||||
// Note: 'tocb' can be reused here to reschedule if needed,
|
|
||||||
// or the memory it points to can be freed if dynamically allocated.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Somewhere in initialization code:
|
|
||||||
static struct timeout_callback my_timer;
|
|
||||||
static struct my_callback_data my_data;
|
|
||||||
|
|
||||||
void schedule_my_task(void)
|
|
||||||
{
|
|
||||||
my_data.counter = 42;
|
|
||||||
my_data.message = "Hello from timer";
|
|
||||||
|
|
||||||
my_timer.priv = &my_data;
|
|
||||||
my_timer.callback = my_callback_handler;
|
|
||||||
|
|
||||||
// Schedule the callback to run after 500 milliseconds (500,000 us)
|
|
||||||
int rc = timer_sched_callback(&my_timer, 500 * 1000);
|
|
||||||
if (rc == 0) {
|
|
||||||
printk(BIOS_DEBUG, "Scheduled my_callback_handler successfully.\n");
|
|
||||||
} else {
|
|
||||||
printk(BIOS_ERR, "Failed to schedule callback!\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remember that timers_run() must be called periodically elsewhere
|
|
||||||
// for the callback to actually execute after the delay.
|
|
||||||
```
|
|
||||||
|
|
||||||
## Best Practices
|
|
||||||
|
|
||||||
1. **Enable Monotonic Timer:** For accurate timing and stopwatch
|
|
||||||
functionality, ensure `CONFIG(HAVE_MONOTONIC_TIMER)` is enabled and a
|
|
||||||
suitable platform timer is configured.
|
|
||||||
2. **Minimize Stopwatch Overhead:** While lightweight, frequent calls,
|
|
||||||
especially `timer_monotonic_get()` implicitly called by stopwatch
|
|
||||||
functions, can add up. Measure larger, significant code blocks rather
|
|
||||||
than tiny ones in tight loops unless absolutely necessary.
|
|
||||||
3. **Use Appropriate Time Units:** Choose `usecs` or `msecs` variants
|
|
||||||
based on the scale of time you are dealing with.
|
|
||||||
4. **Handle Timeouts Gracefully:** When using expiration or
|
|
||||||
`wait_ms`/`wait_us`, always check the result and handle the timeout
|
|
||||||
case appropriately. Don't assume success.
|
|
||||||
5. **Process Timer Callbacks:** If using `timer_sched_callback`, ensure
|
|
||||||
`timers_run()` is called regularly in your main processing loops or
|
|
||||||
idle states.
|
|
||||||
6. **Avoid `mdelay` for Polling:** Prefer `wait_ms` or manual polling
|
|
||||||
with `stopwatch_expired` when waiting for conditions, as `mdelay`
|
|
||||||
offers no timeout handling or feedback.
|
|
||||||
7. **Consider Platform Accuracy:** Timer resolution and accuracy vary
|
|
||||||
between platforms. Don't assume microsecond precision unless verified
|
|
||||||
for the target hardware.
|
|
||||||
|
|
||||||
|
|
||||||
## Limitations
|
|
||||||
|
|
||||||
1. **Monotonic Timer Dependence:** Stopwatch and timer callbacks rely
|
|
||||||
heavily on `CONFIG(HAVE_MONOTONIC_TIMER)`. Without it, their
|
|
||||||
behavior is limited.
|
|
||||||
2. **Timer Resolution:** Accuracy is limited by the underlying platform
|
|
||||||
timer's resolution and the frequency of `timer_monotonic_get()`
|
|
||||||
updates internally.
|
|
||||||
3. **64-bit Microsecond Counter:** While large, the
|
|
||||||
`uint64_t microseconds` counter will eventually wrap around
|
|
||||||
(after ~584,000 years), though this is not a practical concern for
|
|
||||||
boot times. More relevant is the potential rollover of the
|
|
||||||
*underlying hardware counter* between `timer_monotonic_get` calls,
|
|
||||||
which the implementation must handle correctly (typically ok for
|
|
||||||
intervals up to several seconds).
|
|
||||||
4. **Busy Waiting:** `stopwatch_wait_until_expired` and the internal
|
|
||||||
loops of `wait_us`/`wait_ms` (and potentially the fallback in
|
|
||||||
`udelay`/`mdelay`) perform busy-waits, consuming CPU cycles. Consider
|
|
||||||
alternatives like interrupt-driven timers or yielding
|
|
||||||
(`thread_yield_microseconds`) if power consumption or concurrency is
|
|
||||||
critical.
|
|
||||||
5. **Callback Queue Size:** The timer callback queue has a fixed size
|
|
||||||
defined by `CONFIG(TIMER_QUEUE_SIZE)`, limiting the number of pending
|
|
||||||
callbacks.
|
|
||||||
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
Common issues and solutions:
|
|
||||||
|
|
||||||
1. **Inaccurate Timing / Durations are Zero:**
|
|
||||||
- Verify `CONFIG(HAVE_MONOTONIC_TIMER)` is enabled.
|
|
||||||
- Check if a platform-specific `init_timer()` is required and being
|
|
||||||
called.
|
|
||||||
- Ensure the platform timer frequency is correctly configured.
|
|
||||||
- Check for potential timer hardware issues or conflicts.
|
|
||||||
|
|
||||||
2. **Timeouts Not Working / `wait_ms` Never Returns > 0:**
|
|
||||||
- Verify the timeout value is appropriate (not too short).
|
|
||||||
- Double-check the `condition` logic in `wait_ms`/`wait_us`. Is it
|
|
||||||
actually capable of becoming true?
|
|
||||||
- Ensure the stopwatch (`sw` or the internal one in `wait_ms`) is
|
|
||||||
properly initialized before the check loop.
|
|
||||||
- Confirm `CONFIG(HAVE_MONOTONIC_TIMER)` is enabled.
|
|
||||||
|
|
||||||
3. **Timer Callbacks Not Running:**
|
|
||||||
- Verify `CONFIG(TIMER_QUEUE)` is enabled.
|
|
||||||
- Ensure `timer_sched_callback()` returned success (0).
|
|
||||||
- **Crucially:** Check that `timers_run()` is being called
|
|
||||||
periodically in a suitable loop after the callback was scheduled.
|
|
||||||
- Make sure the `struct timeout_callback` structure persists in memory
|
|
||||||
until the callback runs.
|
|
||||||
|
|
||||||
4. **Performance Impact:**
|
|
||||||
- Reduce frequency of stopwatch checks or `wait_ms`/`wait_us` calls if
|
|
||||||
possible.
|
|
||||||
- Measure larger code blocks.
|
|
||||||
- Investigate if the underlying `udelay` implementation is
|
|
||||||
busy-waiting excessively; yielding (`thread_yield_microseconds`)
|
|
||||||
might be preferable if available and appropriate.
|
|
||||||
|
|
||||||
|
|
||||||
## Platform-Specific Considerations
|
|
||||||
|
|
||||||
The core APIs are generic, but the underlying implementation relies on
|
|
||||||
platform code:
|
|
||||||
- **Timer Source:** Platforms implement `timer_monotonic_get` (often
|
|
||||||
weakly linked) or provide the necessary hooks for it, using hardware
|
|
||||||
like the APIC timer (x86), Time Base (PPC), architectural timers
|
|
||||||
(ARM), etc.
|
|
||||||
- **`init_timer()`:** Platforms may need a custom `init_timer` to set up
|
|
||||||
clocks, dividers, or enable the timer hardware.
|
|
||||||
- **`udelay`:** Platforms might provide optimized `udelay`
|
|
||||||
implementations.
|
|
||||||
|
|
||||||
Refer to the documentation and code within specific `src/soc/`,
|
|
||||||
`src/cpu/`, or `src/arch/` directories for platform details.
|
|
||||||
|
|
||||||
|
|
||||||
## References
|
|
||||||
|
|
||||||
- `src/include/timer.h`: Monotonic timer, stopwatch, and callback
|
|
||||||
declarations.
|
|
||||||
- `src/include/delay.h`: `udelay`, `mdelay`, `delay` declarations.
|
|
||||||
- `src/lib/timer.c`: Generic `udelay` (using stopwatch/yield), weak
|
|
||||||
`init_timer`.
|
|
||||||
- `src/lib/delay.c`: Generic `mdelay` and `delay` implementations
|
|
||||||
(calling `udelay`).
|
|
||||||
- `src/lib/hardwaremain.c`: Example usage of `timers_run()` in boot
|
|
||||||
state machine.
|
|
||||||
- Platform timer implementations: Search for `timer_monotonic_get` or
|
|
||||||
`init_timer` in `src/cpu/`, `src/soc/`, `src/arch/` directories
|
|
||||||
(e.g., `src/cpu/x86/lapic/apic_timer.c`,
|
|
||||||
`src/arch/arm64/timer.c`).
|
|
||||||
|
|
@ -1,310 +0,0 @@
|
||||||
# coreboot Threads
|
|
||||||
|
|
||||||
## Thread Management
|
|
||||||
|
|
||||||
coreboot provides a cooperative threading system that allows for
|
|
||||||
concurrent execution of tasks during the boot process. The thread API is
|
|
||||||
particularly useful for implementing asynchronous operations and
|
|
||||||
managing hardware initialization sequences.
|
|
||||||
|
|
||||||
|
|
||||||
### Thread Creation and Management
|
|
||||||
|
|
||||||
#### thread_run
|
|
||||||
|
|
||||||
```c
|
|
||||||
int thread_run(struct thread_handle *handle, enum cb_err (*func)(void *), void *arg)
|
|
||||||
```
|
|
||||||
Creates and starts a new thread to execute the specified function.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `handle`: Pointer to a thread handle structure to track thread state
|
|
||||||
(Note: `struct thread_handle` is an opaque structure used by the API
|
|
||||||
to manage the thread's state.)
|
|
||||||
- `func`: Function to execute in the new thread
|
|
||||||
- `arg`: Argument to pass to the function
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
- 0 on success
|
|
||||||
- < 0 on failure
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
```c
|
|
||||||
struct thread_handle th;
|
|
||||||
enum cb_err thread_func(void *arg) {
|
|
||||||
// Thread work here
|
|
||||||
return CB_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thread_run(&th, thread_func, NULL) < 0) {
|
|
||||||
printk(BIOS_ERR, "Failed to create thread\n");
|
|
||||||
} else {
|
|
||||||
// Wait for the thread to complete and check its status
|
|
||||||
enum cb_err err = thread_join(&th);
|
|
||||||
if (err != CB_SUCCESS) {
|
|
||||||
printk(BIOS_ERR, "Thread failed with error %d\n", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### thread_run_until
|
|
||||||
|
|
||||||
```c
|
|
||||||
int thread_run_until(struct thread_handle *handle, enum cb_err (*func)(void *), void *arg,
|
|
||||||
boot_state_t state, boot_state_sequence_t seq)
|
|
||||||
```
|
|
||||||
Creates a thread that blocks boot state transitions until completion.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `handle`: Pointer to a thread handle structure
|
|
||||||
- `func`: Function to execute
|
|
||||||
- `arg`: Argument to pass to the function
|
|
||||||
- `state`: Boot state to block
|
|
||||||
- `seq`: Boot state sequence to block
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
- 0 on success
|
|
||||||
- < 0 on failure
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
```c
|
|
||||||
struct thread_handle th;
|
|
||||||
enum cb_err init_func(void *arg) {
|
|
||||||
// Hardware initialization
|
|
||||||
return CB_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Block BS_DEV_ENABLE until initialization completes
|
|
||||||
thread_run_until(&th, init_func, NULL, BS_DEV_ENABLE, 0);
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Thread Synchronization
|
|
||||||
|
|
||||||
#### thread_join
|
|
||||||
|
|
||||||
```c
|
|
||||||
enum cb_err thread_join(struct thread_handle *handle)
|
|
||||||
```
|
|
||||||
Waits for a thread to complete and returns its error code.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `handle`: Thread handle to wait for
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
- Thread's error code (e.g., `CB_SUCCESS`, `CB_ERR`). See
|
|
||||||
`src/include/cb_err.h` for details.
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
```c
|
|
||||||
struct thread_handle th;
|
|
||||||
// ... create thread ...
|
|
||||||
|
|
||||||
enum cb_err err = thread_join(&th);
|
|
||||||
if (err != CB_SUCCESS) {
|
|
||||||
printk(BIOS_ERR, "Thread failed with error %d\n", err);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Thread Yielding
|
|
||||||
|
|
||||||
Yielding is crucial in a cooperative multitasking system like
|
|
||||||
coreboot's. Threads must explicitly yield control using `thread_yield`
|
|
||||||
or `thread_yield_microseconds` to allow other threads to run. Failure to
|
|
||||||
yield can lead to a single thread monopolizing the CPU, preventing other
|
|
||||||
tasks from executing.
|
|
||||||
|
|
||||||
#### thread_yield
|
|
||||||
|
|
||||||
```c
|
|
||||||
int thread_yield(void)
|
|
||||||
```
|
|
||||||
Yields the current thread's execution to allow other threads to run.
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
- 0 on success
|
|
||||||
- < 0 if thread cannot yield
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
```c
|
|
||||||
while (!condition) {
|
|
||||||
if (thread_yield() < 0) {
|
|
||||||
printk(BIOS_ERR, "Failed to yield thread\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### thread_yield_microseconds
|
|
||||||
|
|
||||||
```c
|
|
||||||
int thread_yield_microseconds(unsigned int microsecs)
|
|
||||||
```
|
|
||||||
Yields the current thread for a specified number of microseconds.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `microsecs`: Number of microseconds to yield
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
- 0 on success
|
|
||||||
- < 0 if thread cannot yield
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
```c
|
|
||||||
// Wait for 100 microseconds
|
|
||||||
if (thread_yield_microseconds(100) < 0) {
|
|
||||||
printk(BIOS_ERR, "Failed to yield thread\n");
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Thread Cooperation Control
|
|
||||||
|
|
||||||
#### thread_coop_enable
|
|
||||||
|
|
||||||
```c
|
|
||||||
void thread_coop_enable(void)
|
|
||||||
```
|
|
||||||
Enables cooperative behavior for the current thread.
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
```c
|
|
||||||
thread_coop_enable(); // Allow thread to yield
|
|
||||||
```
|
|
||||||
|
|
||||||
#### thread_coop_disable
|
|
||||||
|
|
||||||
```c
|
|
||||||
void thread_coop_disable(void)
|
|
||||||
```
|
|
||||||
Disables cooperative behavior for the current thread.
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
```c
|
|
||||||
thread_coop_disable(); // Prevent thread from yielding
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Thread Mutexes
|
|
||||||
|
|
||||||
#### thread_mutex_lock
|
|
||||||
|
|
||||||
```c
|
|
||||||
void thread_mutex_lock(struct thread_mutex *mutex)
|
|
||||||
```
|
|
||||||
Acquires a mutex lock, waiting if necessary.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `mutex`: Mutex to lock
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
```c
|
|
||||||
struct thread_mutex mtx = THREAD_MUTEX_INITIALIZER; // Or = { .locked = false };
|
|
||||||
thread_mutex_lock(&mtx);
|
|
||||||
// Critical section
|
|
||||||
thread_mutex_unlock(&mtx);
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### thread_mutex_unlock
|
|
||||||
|
|
||||||
```c
|
|
||||||
void thread_mutex_unlock(struct thread_mutex *mutex)
|
|
||||||
```
|
|
||||||
Releases a mutex lock.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
- `mutex`: Mutex to unlock
|
|
||||||
|
|
||||||
## Best Practices
|
|
||||||
|
|
||||||
1. **Thread Safety**:
|
|
||||||
- Use mutexes to protect shared resources
|
|
||||||
- Be careful with global variables in threaded code
|
|
||||||
- Consider thread cooperation when implementing critical sections
|
|
||||||
|
|
||||||
2. **Resource Management**:
|
|
||||||
- Always join threads that you create using `thread_run` to check
|
|
||||||
their completion status and clean up resources. Threads started
|
|
||||||
with `thread_run_until` are implicitly managed by the boot state
|
|
||||||
machine and typically do not require explicit joining.
|
|
||||||
- Consistently check return values from thread creation and operation
|
|
||||||
functions (like `thread_run`, `thread_yield`, `thread_join`) to
|
|
||||||
detect errors early.
|
|
||||||
- Clean up resources allocated or used within thread functions before
|
|
||||||
they exit.
|
|
||||||
|
|
||||||
3. **Performance Considerations**:
|
|
||||||
- Use thread_yield_microseconds for precise timing
|
|
||||||
- Minimize time spent in critical sections
|
|
||||||
- Consider using thread_run_until for hardware initialization
|
|
||||||
|
|
||||||
4. **Error Handling**:
|
|
||||||
- Check thread creation and operation return values (as noted in
|
|
||||||
Resource Management).
|
|
||||||
- Implement proper error handling within thread functions, returning
|
|
||||||
appropriate `cb_err` values.
|
|
||||||
- Use `thread_join` (for `thread_run` threads) to check the final
|
|
||||||
completion status.
|
|
||||||
|
|
||||||
|
|
||||||
## Common Patterns
|
|
||||||
|
|
||||||
### Hardware Initialization
|
|
||||||
|
|
||||||
```c
|
|
||||||
struct thread_handle init_th;
|
|
||||||
enum cb_err init_hardware(void *arg) {
|
|
||||||
// Initialize hardware
|
|
||||||
if (hardware_init() != 0)
|
|
||||||
return CB_ERR;
|
|
||||||
return CB_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run initialization in a thread
|
|
||||||
thread_run_until(&init_th, init_hardware, NULL, BS_DEV_ENABLE, 0);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Asynchronous Operation
|
|
||||||
|
|
||||||
```c
|
|
||||||
struct thread_handle async_th;
|
|
||||||
enum cb_err async_operation(void *arg) {
|
|
||||||
// Perform async operation
|
|
||||||
while (!operation_complete()) {
|
|
||||||
if (thread_yield() < 0)
|
|
||||||
return CB_ERR;
|
|
||||||
}
|
|
||||||
return CB_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start async operation
|
|
||||||
thread_run(&async_th, async_operation, NULL);
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Critical Section Protection
|
|
||||||
|
|
||||||
```c
|
|
||||||
struct thread_mutex resource_mtx = { .locked = false };
|
|
||||||
|
|
||||||
void access_shared_resource(void) {
|
|
||||||
thread_mutex_lock(&resource_mtx);
|
|
||||||
// Access shared resource
|
|
||||||
thread_mutex_unlock(&resource_mtx);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Limitations
|
|
||||||
|
|
||||||
1. The thread system is cooperative, not preemptive.
|
|
||||||
2. Threads must explicitly yield to allow other threads to run.
|
|
||||||
3. Thread operations are typically only available after RAM
|
|
||||||
initialization (in ramstage and later). Check specific environment
|
|
||||||
constraints if unsure.
|
|
||||||
4. Thread count is limited by the `CONFIG_NUM_THREADS` Kconfig option.
|
|
||||||
5. Thread stack size is fixed by the `CONFIG_STACK_SIZE` Kconfig option.
|
|
||||||
|
|
||||||
|
|
@ -2,408 +2,175 @@
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
The aim of the timestamp library is to make it easier for different
|
The aim of the timestamp library is to make it easier for different boards
|
||||||
boards to save timestamps in cbmem / stash (until cbmem is brought up)
|
to save timestamps in cbmem / stash (until cbmem is brought up) by
|
||||||
by providing a simple API to initialize, add, and sync timestamps. In
|
providing a simple API to initialize, add and sync timestamps. In order
|
||||||
order to make the timestamps persistent and accessible from the kernel,
|
to make the timestamps persistent and accessible from the kernel, we
|
||||||
we need to ensure that all the saved timestamps end up in cbmem under
|
need to ensure that all the saved timestamps end up in cbmem under
|
||||||
the CBMEM_ID_TIMESTAMP tag. However, until the cbmem area is available,
|
the CBMEM_ID_TIMESTAMP tag. However, until the cbmem area is available,
|
||||||
the timestamps can be saved to a SoC-defined `_timestamp` region if one
|
the timestamps can be saved to a SoC-defined \_timestamp region or in a
|
||||||
is defined in the board's `memlayout.ld`. The work of identifying the
|
local stage-specific stash. The work of identifying the right location for
|
||||||
right location for storing timestamps is done by the library and is not
|
storing timestamps is done by the library and is not exposed to the user.
|
||||||
exposed to the user.
|
|
||||||
|
|
||||||
Timestamps in coreboot are a critical feature for performance analysis,
|
|
||||||
debugging, and optimization of the boot process. They provide precise
|
|
||||||
timing information about various stages and operations during system
|
|
||||||
initialization, allowing developers to identify bottlenecks and optimize
|
|
||||||
boot performance. The timestamp system is designed to be lightweight,
|
|
||||||
accurate, and persistent across different boot stages.
|
|
||||||
|
|
||||||
Working of timestamp library from a user perspective can be outlined in
|
Working of timestamp library from a user perspective can be outlined in
|
||||||
the following steps:
|
the following steps:
|
||||||
1. Initialize the base time and reset cbmem timestamp area using
|
1. Initialize the base time and reset cbmem timestamp area
|
||||||
`timestamp_init()`.
|
2. Start adding timestamps
|
||||||
2. Start adding timestamps using `timestamp_add()` or
|
|
||||||
`timestamp_add_now()`.
|
|
||||||
|
|
||||||
Behind the scenes, the timestamp library takes care of:
|
Behind the scenes, the timestamp library takes care of:
|
||||||
1. Identifying the correct location for storing timestamps (`_timestamp`
|
1. Identifying the correct location for storing timestamps (cbmem or timestamp
|
||||||
region before cbmem is ready, then cbmem region).
|
region or local stash).
|
||||||
2. Add a new cbmem timestamp area based on whether a reset of the cbmem
|
2. Once cbmem is up, ensure that all timestamps are synced from timestamp
|
||||||
|
region or local stash into the cbmem area.
|
||||||
|
3. Add a new cbmem timestamp area based on whether a reset of the cbmem
|
||||||
timestamp region is required or not.
|
timestamp region is required or not.
|
||||||
3. Once cbmem is ready, ensuring that all timestamps are synced from the
|
|
||||||
`_timestamp` region into the cbmem area.
|
|
||||||
|
|
||||||
Note that if `CONFIG_COLLECT_TIMESTAMPS` is disabled, all timestamp
|
### Transition from cache to cbmem
|
||||||
functions are implemented as no-ops, and no timestamps will be
|
|
||||||
collected.
|
To move timestamps from the cache to cbmem (and initialize the cbmem area in
|
||||||
|
the first place), we use the CBMEM_INIT_HOOK infrastructure of coreboot.
|
||||||
|
|
||||||
|
When cbmem is initialized, the hook is called, which creates the area,
|
||||||
|
copies all timestamps to cbmem and disables the cache.
|
||||||
|
|
||||||
|
After such a transition, timestamp_init() must not be run again.
|
||||||
|
|
||||||
|
|
||||||
## Background
|
## Data structures used
|
||||||
|
|
||||||
The timestamp implementation in coreboot has evolved over time to meet
|
|
||||||
the needs of the firmware development and performance analysis.
|
|
||||||
Initially designed as a simple timing mechanism, it has grown into a
|
|
||||||
sophisticated system that:
|
|
||||||
|
|
||||||
- Tracks boot stages and critical operations
|
|
||||||
- Supports multiple hardware platforms (x86, ARM, RISC-V)
|
|
||||||
- Provides persistent storage across boot stages
|
|
||||||
- Enables post-boot analysis of boot performance
|
|
||||||
- Integrates with vendor-specific firmware components
|
|
||||||
|
|
||||||
|
|
||||||
## Timestamp Architecture
|
|
||||||
|
|
||||||
### Transition from cache (`_timestamp` region) to cbmem
|
|
||||||
|
|
||||||
To move timestamps from the early `_timestamp` region to cbmem (and
|
|
||||||
initialize the cbmem area in the first place), we use the
|
|
||||||
`CBMEM_READY_HOOK` infrastructure of coreboot.
|
|
||||||
|
|
||||||
When cbmem is initialized (`cbmem_initialize` or `cbmem_recovery`), the
|
|
||||||
hook calls the `timestamp_reinit` function. This function allocates or
|
|
||||||
finds the `CBMEM_ID_TIMESTAMP` area in cbmem, copies all timestamps from
|
|
||||||
the `_timestamp` region (if used) using `timestamp_sync_cache_to_cbmem`,
|
|
||||||
and updates an internal global pointer (`glob_ts_table`) to point to the
|
|
||||||
cbmem table. Subsequent calls to `timestamp_add` will then write
|
|
||||||
directly to cbmem.
|
|
||||||
|
|
||||||
After such a transition, `timestamp_init()` must not be run again (it is
|
|
||||||
asserted to only run in `ENV_ROMSTAGE_OR_BEFORE`).
|
|
||||||
|
|
||||||
|
|
||||||
### Data structures used
|
|
||||||
|
|
||||||
Timestamps are stored using instances of `struct timestamp_table`. A
|
|
||||||
global pointer, `glob_ts_table`, points to the currently active table,
|
|
||||||
which is either the `_timestamp` memory region (during early boot) or
|
|
||||||
the CBMEM area.
|
|
||||||
|
|
||||||
The `_timestamp` region acts as an early cache before cbmem is ready.
|
|
||||||
Its size is determined by `REGION_SIZE(timestamp)` defined in the linker
|
|
||||||
script (`memlayout.ld`) and dictates the maximum number of entries that
|
|
||||||
can be stored early on.
|
|
||||||
|
|
||||||
For timestamps stored in the cbmem area, a `timestamp_table` is
|
|
||||||
allocated with space for a fixed number of entries (currently 192)
|
|
||||||
defined by `MAX_TIMESTAMPS` in `src/lib/timestamp.c`.
|
|
||||||
|
|
||||||
|
The main structure that maintains information about the timestamp cache is:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
struct timestamp_entry {
|
struct __packed timestamp_cache {
|
||||||
uint32_t entry_id;
|
uint16_t cache_state;
|
||||||
int64_t entry_stamp;
|
struct timestamp_table table;
|
||||||
} __packed;
|
struct timestamp_entry entries[MAX_TIMESTAMP_CACHE];
|
||||||
|
};
|
||||||
```
|
```
|
||||||
>>> _Source: `/src/commonlib/include/commonlib/timestamp_serialized.h`_
|
|
||||||
|
|
||||||
|
### cache_state
|
||||||
|
|
||||||
|
The state of the cache is maintained by `cache_state` attribute which can
|
||||||
|
be any one of the following:
|
||||||
|
|
||||||
|
```c
|
||||||
|
enum {
|
||||||
|
TIMESTAMP_CACHE_UNINITIALIZED = 0,
|
||||||
|
TIMESTAMP_CACHE_INITIALIZED,
|
||||||
|
TIMESTAMP_CACHE_NOT_NEEDED,
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, if the cache is stored in local stash (bss area), then
|
||||||
|
it will be reset to uninitialized state. However, if the cache is
|
||||||
|
stored in timestamp region, then it might have garbage in any of the
|
||||||
|
attributes. Thus, if the timestamp region is being used by any board, it is
|
||||||
|
initialized to default values by the library.
|
||||||
|
|
||||||
|
Once the cache is initialized, its state is set to
|
||||||
|
`CACHE_INITIALIZED`. Henceforth, the calls to cache i.e. `timestamp_add`
|
||||||
|
know that the state reflected is valid and timestamps can be directly
|
||||||
|
saved in the cache.
|
||||||
|
|
||||||
|
Once the cbmem area is up (i.e. call to `timestamp_sync_cache_to_cbmem`),
|
||||||
|
we do not need to store the timestamps in local stash / timestamp area
|
||||||
|
anymore. Thus, the cache state is set to `CACHE_NOT_NEEDED`, which allows
|
||||||
|
`timestamp_add` to store all timestamps directly into the cbmem area.
|
||||||
|
|
||||||
|
|
||||||
|
### table
|
||||||
|
|
||||||
|
This field is represented by a structure which provides overall
|
||||||
|
information about the entries in the timestamp area:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
struct timestamp_table {
|
struct timestamp_table {
|
||||||
uint64_t base_time;
|
uint64_t base_time;
|
||||||
uint16_t max_entries;
|
uint32_t max_entries;
|
||||||
uint16_t tick_freq_mhz;
|
uint32_t num_entries;
|
||||||
uint32_t num_entries;
|
struct timestamp_entry entries[0]; /* Variable number of entries */
|
||||||
struct timestamp_entry entries[]; /* Variable number of entries */
|
|
||||||
} __packed;
|
} __packed;
|
||||||
```
|
```
|
||||||
>>> _Source: `/src/commonlib/include/commonlib/timestamp_serialized.h`_
|
|
||||||
|
It indicates the base time for all timestamp entries, maximum number
|
||||||
|
of entries that can be stored, total number of entries that currently
|
||||||
|
exist and an entry structure to hold variable number of entries.
|
||||||
|
|
||||||
|
|
||||||
- `base_time`: Indicates the base time (offset) for all timestamp
|
### entries
|
||||||
entries in this table.
|
|
||||||
- `max_entries`: Maximum number of entries that can be stored in this
|
This field holds the details of each timestamp entry, up to a maximum
|
||||||
table instance.
|
of `MAX_TIMESTAMP_CACHE` which is defined as 16 entries. Each entry is
|
||||||
- `tick_freq_mhz`: Timestamp tick frequency in MHz. Populated later in
|
defined by:
|
||||||
boot.
|
|
||||||
- `num_entries`: Total number of entries that currently exist in this
|
```c
|
||||||
table instance.
|
struct timestamp_entry {
|
||||||
- `entries`: Array holding the actual timestamp entries.
|
uint32_t entry_id;
|
||||||
|
uint64_t entry_stamp;
|
||||||
|
} __packed;
|
||||||
|
```
|
||||||
|
|
||||||
|
`entry_id` holds the timestamp id corresponding to this entry and
|
||||||
|
`entry_stamp` holds the actual timestamp.
|
||||||
|
|
||||||
|
|
||||||
### Memory Layout
|
For timestamps stored in the cbmem area, a `timestamp_table` is allocated
|
||||||
|
with space for `MAX_TIMESTAMPS` equal to 30. Thus, the cbmem area holds
|
||||||
Timestamps are stored in two locations during the boot process:
|
`base_time`, `max_entries` (which is 30), current number of entries and the
|
||||||
|
actual entries represented by `timestamp_entry`.
|
||||||
1. **`_timestamp` Region**: Used during early boot stages (before CBMEM
|
|
||||||
is available), *if* defined in `memlayout.ld`.
|
|
||||||
- Located at the `_timestamp` symbol.
|
|
||||||
- Persists across stage transitions within `ENV_ROMSTAGE_OR_BEFORE`.
|
|
||||||
- Size determined by `REGION_SIZE(timestamp)` in the linker script,
|
|
||||||
which limits the number of entries.
|
|
||||||
|
|
||||||
2. **CBMEM**: Used after CBMEM is initialized.
|
|
||||||
- Identified by `CBMEM_ID_TIMESTAMP`.
|
|
||||||
- Provides persistent storage across warm reboots.
|
|
||||||
- Supports a fixed maximum number of entries.
|
|
||||||
- Automatically synchronized from the `_timestamp` region when CBMEM
|
|
||||||
becomes available via `timestamp_reinit`.
|
|
||||||
|
|
||||||
|
|
||||||
## Function APIs
|
## Function APIs
|
||||||
|
|
||||||
### Core Functions
|
### timestamp_init
|
||||||
|
|
||||||
#### timestamp_init
|
This function initializes the timestamp cache and should be run as early
|
||||||
|
as possible. On platforms with SRAM, this might mean in bootblock, on
|
||||||
|
x86 with its CAR backed memory in romstage, this means romstage before
|
||||||
|
memory init.
|
||||||
|
|
||||||
```c
|
### timestamp_add
|
||||||
void timestamp_init(uint64_t base);
|
|
||||||
```
|
|
||||||
>>> _Source: `/src/include/timestamp.h`_
|
|
||||||
|
|
||||||
Initializes the timestamp system with a base time. This function sets up
|
This function accepts from user a timestamp id and time to record in the
|
||||||
the timestamp cache (`_timestamp` region) and should be run in
|
timestamp table. It stores the entry in the appropriate table in cbmem
|
||||||
bootblock. It must be called once in *one* of the
|
or `_timestamp` region or local stash.
|
||||||
`ENV_ROMSTAGE_OR_BEFORE` stages. It will fail if no `timestamp` region
|
|
||||||
is defined in `memlayout.ld`.
|
|
||||||
|
|
||||||
Note that platform setup code on x86 or the decompressor on Arm can
|
|
||||||
measure some timestamps earlier and pass them in to
|
|
||||||
bootblock_main_with_timestamp().
|
|
||||||
|
|
||||||
|
|
||||||
#### timestamp_add
|
### timestamp_add_now
|
||||||
|
|
||||||
```c
|
This function calls `timestamp_add` with user-provided id and current time.
|
||||||
void timestamp_add(enum timestamp_id id, int64_t ts_time);
|
|
||||||
```
|
|
||||||
>>> _Source: `/src/include/timestamp.h`_
|
|
||||||
|
|
||||||
Adds a new timestamp with the specified ID and time value. It stores the
|
|
||||||
timestamp in the currently active table (either `_timestamp` region or
|
|
||||||
cbmem). The time value must be an absolute time value (typically
|
|
||||||
obtained from `timestamp_get()`), as it will be adjusted by subtracting
|
|
||||||
the table's `base_time` before being stored as an entry.
|
|
||||||
|
|
||||||
|
|
||||||
#### timestamp_add_now
|
|
||||||
|
|
||||||
```c
|
|
||||||
void timestamp_add_now(enum timestamp_id id);
|
|
||||||
```
|
|
||||||
>>> _Source: `/src/include/timestamp.h`_
|
|
||||||
|
|
||||||
Adds a new timestamp with the current time. This function calls
|
|
||||||
`timestamp_add` with user-provided id and current time obtained from
|
|
||||||
`timestamp_get()`.
|
|
||||||
|
|
||||||
|
|
||||||
#### timestamp_rescale_table
|
|
||||||
|
|
||||||
```c
|
|
||||||
void timestamp_rescale_table(uint16_t N, uint16_t M);
|
|
||||||
```
|
|
||||||
>>> _Source: `/src/include/timestamp.h`_
|
|
||||||
|
|
||||||
Applies a scaling factor N/M to all recorded timestamps (including the
|
|
||||||
`base_time`).
|
|
||||||
|
|
||||||
|
|
||||||
#### get_us_since_boot
|
|
||||||
|
|
||||||
```c
|
|
||||||
uint32_t get_us_since_boot(void);
|
|
||||||
```
|
|
||||||
>>> _Source: `/src/include/timestamp.h`_
|
|
||||||
|
|
||||||
Returns the time since boot (relative to `base_time`) in microseconds.
|
|
||||||
Requires `tick_freq_mhz` to be populated.
|
|
||||||
|
|
||||||
|
|
||||||
#### timestamp_get
|
|
||||||
|
|
||||||
```c
|
|
||||||
uint64_t timestamp_get(void);
|
|
||||||
```
|
|
||||||
>>> _Source: `/src/include/timestamp.h`_
|
|
||||||
|
|
||||||
Returns the current raw timestamp value from the underlying hardware
|
|
||||||
timer (platform-specific weak implementation).
|
|
||||||
|
|
||||||
|
|
||||||
#### timestamp_tick_freq_mhz
|
|
||||||
|
|
||||||
```c
|
|
||||||
int timestamp_tick_freq_mhz(void);
|
|
||||||
```
|
|
||||||
>>> _Source: `/src/include/timestamp.h`_
|
|
||||||
|
|
||||||
Returns the timestamp tick frequency in MHz (platform-specific weak
|
|
||||||
implementation).
|
|
||||||
|
|
||||||
|
|
||||||
### Timestamp IDs
|
|
||||||
|
|
||||||
The system uses predefined timestamp IDs to mark various boot stages and
|
|
||||||
operations. These are organized in ranges:
|
|
||||||
|
|
||||||
- 1-500: Miscellaneous coreboot operations (e.g., `TS_POSTCAR_START`,
|
|
||||||
`TS_DELAY_START`, `TS_READ_UCODE_START`)
|
|
||||||
- 500-600: Google/ChromeOS specific (e.g., `TS_VBOOT_START`,
|
|
||||||
`TS_EC_SYNC_START`).
|
|
||||||
|
|
||||||
Note many of the existing timestamps here are no longer
|
|
||||||
Google-specific since many features originally added for Google
|
|
||||||
vendorcode have since been migrated into general coreboot code.
|
|
||||||
|
|
||||||
- 900-940: AMD specific (e.g., `TS_AGESA_INIT_EARLY_START`)
|
|
||||||
- 940-950: Intel ME specific (e.g., `TS_ME_INFORM_DRAM_START`)
|
|
||||||
- 950-989: Intel FSP specific (e.g., `TS_FSP_MEMORY_INIT_START`)
|
|
||||||
- 990-999: Intel ME specific (continued) (e.g., `TS_ME_ROM_START`)
|
|
||||||
- 1000+: Payload specific
|
|
||||||
- Depthcharge: 1000-1199
|
|
||||||
- ChromeOS Hypervisor: 1200-1299
|
|
||||||
|
|
||||||
Refer to `src/commonlib/include/commonlib/timestamp_serialized.h` for
|
|
||||||
the complete list and descriptions.
|
|
||||||
|
|
||||||
|
|
||||||
## Use / Test Cases
|
## Use / Test Cases
|
||||||
|
|
||||||
The following cases describe the behavior based on the presence of the
|
The following cases have been considered while designing the timestamp
|
||||||
`timestamp` region and when cbmem is initialized.
|
library. It is important to ensure that any changes made to this library satisfy
|
||||||
|
each of the following use cases:
|
||||||
|
|
||||||
|
### Case 1: Timestamp Region Exists (Fresh Boot / Resume)
|
||||||
|
|
||||||
### Case 1: Timestamp Region Exists
|
In this case, the library needs to call `timestamp_init` as early as possible to
|
||||||
|
enable the timestamp cache. Once cbmem is available, the values will be
|
||||||
|
transferred automatically.
|
||||||
|
|
||||||
This is the standard configuration for collecting early timestamps.
|
All regions are automatically reset on initialization.
|
||||||
`timestamp_init` must be called in an `ENV_ROMSTAGE_OR_BEFORE` stage to
|
|
||||||
initialize the `_timestamp` region. When the `CBMEM_READY_HOOK` runs
|
|
||||||
`timestamp_reinit`, the contents of the `_timestamp` region are copied
|
|
||||||
to the cbmem table, and subsequent timestamps go directly to cbmem. The
|
|
||||||
cbmem table is reset on fresh boot or resume.
|
|
||||||
|
|
||||||
|
### Case 2: No timestamp region, fresh boot, cbmem_initialize called after timestamp_init
|
||||||
|
|
||||||
### Case 2: No Timestamp Region Defined
|
`timestamp_init` will set up a local cache. cbmem must be initialized before that
|
||||||
|
cache vanishes - as happens when jumping to the next stage.
|
||||||
|
|
||||||
If no `timestamp` region is defined in `memlayout.ld`, attempts to call
|
### Case 3: No timestamp region, fresh boot, cbmem_initialize called before timestamp_init
|
||||||
`timestamp_init` will fail (specifically, `timestamp_cache_get()` will
|
|
||||||
return NULL). No timestamps can be collected before cbmem is ready.
|
|
||||||
Timestamps added after `timestamp_reinit` has run (via the
|
|
||||||
`CBMEM_READY_HOOK`) will be added directly to the cbmem table, but there
|
|
||||||
will be no `base_time` established from early boot.
|
|
||||||
|
|
||||||
|
This case is not supported right now, just don't call `timestamp_init` after
|
||||||
|
`cbmem_initialize`. (Patches to make this more robust are welcome.)
|
||||||
|
|
||||||
### Case 3: Resume
|
### Case 4: No timestamp region, resume, cbmem_initialize called after timestamp_init
|
||||||
|
|
||||||
On resume (e.g., x86 S3), `timestamp_reinit` is typically called again.
|
We always reset the cbmem region before using it, so pre-suspend timestamps
|
||||||
If `ENV_CREATES_CBMEM` is true for the resume path (as it is for x86
|
will be gone.
|
||||||
S3), a new cbmem table is allocated by `timestamp_alloc_cbmem_table`,
|
|
||||||
effectively clearing any pre-suspend timestamps. The `_timestamp` region
|
|
||||||
content (if any) is copied over, but this usually contains stale data
|
|
||||||
from the previous boot's early stages.
|
|
||||||
|
|
||||||
|
### Case 5: No timestamp region, resume, cbmem_initialize called before timestamp_init
|
||||||
|
|
||||||
## Configuration
|
We always reset the cbmem region before using it, so pre-suspend timestamps
|
||||||
|
will be gone.
|
||||||
### Kconfig Options
|
|
||||||
|
|
||||||
- `CONFIG_COLLECT_TIMESTAMPS`: Enable/disable timestamp collection
|
|
||||||
globally. If disabled, timestamp functions become no-ops.
|
|
||||||
- `CONFIG_TIMESTAMPS_ON_CONSOLE`: Print timestamps to console during
|
|
||||||
boot as they are added.
|
|
||||||
|
|
||||||
|
|
||||||
### Memory Layout
|
|
||||||
|
|
||||||
Collecting timestamps before cbmem is ready requires an `_timestamp`
|
|
||||||
region in the memory layout, defined in the `memlayout.ld` linker
|
|
||||||
script. Depending on the platform, the memory layout can be for the
|
|
||||||
board, the SOC, or the Architecture. Any of them will typically follow
|
|
||||||
the following pattern:
|
|
||||||
|
|
||||||
```text
|
|
||||||
#include <memlayout.h>
|
|
||||||
|
|
||||||
...
|
|
||||||
TIMESTAMP(., 0x200)
|
|
||||||
...
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
The size allocated to this region determines the maximum number of
|
|
||||||
timestamps that can be stored before cbmem is available.
|
|
||||||
|
|
||||||
The cbmem timestamp table (`CBMEM_ID_TIMESTAMP`) has a fixed size,
|
|
||||||
currently allowing up to 192 entries. This limit is defined by
|
|
||||||
`MAX_TIMESTAMPS` in `src/lib/timestamp.c`.
|
|
||||||
|
|
||||||
|
|
||||||
### Hardware Considerations
|
|
||||||
|
|
||||||
- x86: `timestamp_init` must be called before CAR (Cache-as-RAM) is torn
|
|
||||||
down if called from bootblock or separate romstage. The library
|
|
||||||
includes checks (`timestamp_should_run`) to ensure timestamps are only
|
|
||||||
added by the primary processor during early boot on AP systems.
|
|
||||||
- ARM: No special considerations noted in the code.
|
|
||||||
- RISC-V: No special considerations noted in the code.
|
|
||||||
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
### Initializing Timestamps (in bootblock)
|
|
||||||
|
|
||||||
```c
|
|
||||||
/* In src/mainboard/$(MAINBOARDDIR)/bootblock.c */
|
|
||||||
#include <timestamp.h>
|
|
||||||
#include <timer.h> /* For timestamp_get() default implementation */
|
|
||||||
|
|
||||||
void bootblock_mainboard_init(void)
|
|
||||||
{
|
|
||||||
/* Initialize timestamp region with current time as base. */
|
|
||||||
timestamp_init(timestamp_get());
|
|
||||||
|
|
||||||
/* Add first timestamp */
|
|
||||||
timestamp_add_now(TS_BOOTBLOCK_START);
|
|
||||||
|
|
||||||
/* ... other bootblock code ... */
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: `timestamp_get()` here provides the initial base time. Requires
|
|
||||||
`CONFIG_COLLECT_TIMESTAMPS=y` and a `timestamp` region.
|
|
||||||
|
|
||||||
|
|
||||||
### Adding Custom Timestamps
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <timestamp.h>
|
|
||||||
|
|
||||||
void my_custom_function(void)
|
|
||||||
{
|
|
||||||
timestamp_add_now(TS_DEVICE_INITIALIZE); /* Use a relevant ID */
|
|
||||||
// ... perform initialization ...
|
|
||||||
timestamp_add_now(TS_DEVICE_DONE); /* Use a relevant ID */
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Best Practices
|
|
||||||
|
|
||||||
1. **Initialization**:
|
|
||||||
- Enable `CONFIG_COLLECT_TIMESTAMPS` if needed.
|
|
||||||
- Define a `timestamp` region in `memlayout.ld` if early
|
|
||||||
timestamps (before cbmem) are required. Ensure it's large enough
|
|
||||||
for the expected number of early entries.
|
|
||||||
- Call `timestamp_init()` exactly once in the earliest possible
|
|
||||||
`ENV_ROMSTAGE_OR_BEFORE` stage (e.g., `bootblock`).
|
|
||||||
- Use a consistent base time, typically `timestamp_get()`.
|
|
||||||
|
|
||||||
2. **Adding Timestamps**:
|
|
||||||
- Use appropriate predefined timestamp IDs from
|
|
||||||
`timestamp_serialized.h` whenever possible. Add custom IDs if
|
|
||||||
necessary, avoiding conflicts.
|
|
||||||
- Add timestamps for significant operations or stage transitions
|
|
||||||
using `timestamp_add_now()`.
|
|
||||||
- Be mindful of the entry limits: the size of the `_timestamp`
|
|
||||||
region for early timestamps, and the fixed limit for the cbmem
|
|
||||||
table. Check for "Timestamp table full" errors in the log.
|
|
||||||
|
|
||||||
3. **Analysis**:
|
|
||||||
- Use the `cbmem -t` utility in the OS (if using LinuxBoot/NERF)
|
|
||||||
to read and display timestamps stored in CBMEM.
|
|
||||||
- Consider the `tick_freq_mhz` (also available in the `cbmem -t`
|
|
||||||
output) when converting raw timestamp differences (`entry_stamp`)
|
|
||||||
to time units. The raw values are offsets from `base_time`.
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ Acer models Aspire M3800, Aspire M5800 and possibly more.
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| Northbridge | Intel G43 (called x4x in coreboot code) |
|
| Northbridge | Intel G43 (called x4x in coreboot code) |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -69,7 +69,7 @@ Tests were done with SeaBIOS 1.14.0 and slackware64-live from 2019-07-12
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+-------------------+---------------------+
|
+-------------------+---------------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+===================+=====================+
|
+===================+=====================+
|
||||||
|
|
@ -122,8 +122,10 @@ $ sudo flashrom \
|
||||||
-w coreboot.rom
|
-w coreboot.rom
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
In addition to the information here, please see the
|
In addition to the information here, please see the
|
||||||
<project:../../tutorial/flashing_firmware/index.md>.
|
:doc:`../../tutorial/flashing_firmware/index`.
|
||||||
|
```
|
||||||
|
|
||||||
### External flashing
|
### External flashing
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ Three items are marked in this picture
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------------+--------------------+
|
+---------------------+--------------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+=====================+====================+
|
+=====================+====================+
|
||||||
|
|
@ -53,7 +53,7 @@ Three items are marked in this picture
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------+------------------------------+
|
+---------------+------------------------------+
|
||||||
| Fan control | Using fintek F81803A |
|
| Fan control | Using fintek F81803A |
|
||||||
+---------------+------------------------------+
|
+---------------+------------------------------+
|
||||||
|
|
@ -63,7 +63,7 @@ Three items are marked in this picture
|
||||||
|
|
||||||
## Description of pictures within this document
|
## Description of pictures within this document
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+----------------------------+----------------------------------------+
|
+----------------------------+----------------------------------------+
|
||||||
|pademelon.jpg | Motherboard with components identified |
|
|pademelon.jpg | Motherboard with components identified |
|
||||||
+----------------------------+----------------------------------------+
|
+----------------------------+----------------------------------------+
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ Intel company provides [Firmware Support Package (2.0)](../../soc/intel/fsp/inde
|
||||||
|
|
||||||
FSP Information:
|
FSP Information:
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+-----------------------------+-------------------+-------------------+
|
+-----------------------------+-------------------+-------------------+
|
||||||
| FSP Project Name | Directory | Specification |
|
| FSP Project Name | Directory | Specification |
|
||||||
+-----------------------------+-------------------+-------------------+
|
+-----------------------------+-------------------+-------------------+
|
||||||
|
|
@ -114,7 +114,7 @@ facing towards the bottom of the board.
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| CPU | Intel Skylake/Kaby Lake (LGA1151) |
|
| CPU | Intel Skylake/Kaby Lake (LGA1151) |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -130,5 +130,5 @@ facing towards the bottom of the board.
|
||||||
|
|
||||||
[ASRock H110M-DVS]: https://www.asrock.com/mb/Intel/H110M-DVS%20R2.0/
|
[ASRock H110M-DVS]: https://www.asrock.com/mb/Intel/H110M-DVS%20R2.0/
|
||||||
[MX25L6473E]: http://www.macronix.com/Lists/Datasheet/Attachments/7380/MX25L6473E,%203V,%2064Mb,%20v1.4.pdf
|
[MX25L6473E]: http://www.macronix.com/Lists/Datasheet/Attachments/7380/MX25L6473E,%203V,%2064Mb,%20v1.4.pdf
|
||||||
[flashrom]: https://flashrom.org/
|
[flashrom]: https://flashrom.org/Flashrom
|
||||||
[H110M-DVS manual]: https://web.archive.org/web/20191023230631/http://asrock.pc.cdn.bitgravity.com/Manual/H110M-DVS%20R2.0.pdf
|
[H110M-DVS manual]: https://web.archive.org/web/20191023230631/http://asrock.pc.cdn.bitgravity.com/Manual/H110M-DVS%20R2.0.pdf
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ Bridge and Ivy Bridge CPUs.
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
|
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -71,7 +71,7 @@ extlinux
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------------+------------+
|
+---------------------+------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+=====================+============+
|
+=====================+============+
|
||||||
|
|
@ -115,8 +115,10 @@ $ sudo flashrom --noverify-all --ifd -i bios -p internal -w coreboot.rom
|
||||||
The use of `--noverify-all` is required since the Management Engine
|
The use of `--noverify-all` is required since the Management Engine
|
||||||
region is not readable even by the host.
|
region is not readable even by the host.
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
In addition to the information here, please see the
|
In addition to the information here, please see the
|
||||||
<project:../../tutorial/flashing_firmware/index.md>.
|
:doc:`../../tutorial/flashing_firmware/index`.
|
||||||
|
```
|
||||||
|
|
||||||
## Hardware monitoring and fan control
|
## Hardware monitoring and fan control
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,9 @@ This page describes how to run coreboot on the [ASRock H81M-HDS].
|
||||||
|
|
||||||
## Required proprietary blobs
|
## Required proprietary blobs
|
||||||
|
|
||||||
Please see <project:../../northbridge/intel/haswell/mrc.bin.md>.
|
```eval_rst
|
||||||
|
Please see :doc:`../../northbridge/intel/haswell/mrc.bin`.
|
||||||
|
```
|
||||||
|
|
||||||
## Building coreboot
|
## Building coreboot
|
||||||
|
|
||||||
|
|
@ -73,8 +75,9 @@ facing towards the bottom of the board.
|
||||||
in coreboot. The `coretemp` driver can still be used for accurate CPU
|
in coreboot. The `coretemp` driver can still be used for accurate CPU
|
||||||
temperature readings from an OS.
|
temperature readings from an OS.
|
||||||
|
|
||||||
Please also see
|
```eval_rst
|
||||||
<project:../../northbridge/intel/haswell/known-issues.md>.
|
Please also see :doc:`../../northbridge/intel/haswell/known-issues`.
|
||||||
|
```
|
||||||
|
|
||||||
## Untested
|
## Untested
|
||||||
|
|
||||||
|
|
@ -108,7 +111,7 @@ Please also see
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| Northbridge | :doc:`../../northbridge/intel/haswell/index` |
|
| Northbridge | :doc:`../../northbridge/intel/haswell/index` |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -126,5 +129,5 @@ Please also see
|
||||||
|
|
||||||
[ASRock H81M-HDS]: https://www.asrock.com/mb/Intel/H81M-HDS/
|
[ASRock H81M-HDS]: https://www.asrock.com/mb/Intel/H81M-HDS/
|
||||||
[W25Q32FV]: https://www.winbond.com/resource-files/w25q32fv%20revi%2010202015.pdf
|
[W25Q32FV]: https://www.winbond.com/resource-files/w25q32fv%20revi%2010202015.pdf
|
||||||
[flashrom]: https://flashrom.org/
|
[flashrom]: https://flashrom.org/Flashrom
|
||||||
[Board manual]: https://web.archive.org/web/20191231093418/http://asrock.pc.cdn.bitgravity.com/Manual/H81M-HDS.pdf
|
[Board manual]: https://web.archive.org/web/20191231093418/http://asrock.pc.cdn.bitgravity.com/Manual/H81M-HDS.pdf
|
||||||
|
|
|
||||||
|
|
@ -1,245 +0,0 @@
|
||||||
# ASRock Industrial IMB-1222 Thin Mini-ITX Motherboard
|
|
||||||
|
|
||||||
This page describes how to run coreboot on the [ASRock IMB-1222].
|
|
||||||
|
|
||||||
## Technology
|
|
||||||
|
|
||||||
```{eval-rst}
|
|
||||||
+---------+---------------------------------------------------------------+
|
|
||||||
| CPU | | Intel 10th Gen (Comet lake-S) Core Processors (LGA-1200) |
|
|
||||||
| | | CPUs over 80W will be limited due to power design |
|
|
||||||
+---------+---------------------------------------------------------------+
|
|
||||||
| DRAM | 2 SO-DIMM slots, DDR4 2933/2666/2400 MHz |
|
|
||||||
+---------+---------------------------------------------------------------+
|
|
||||||
| Chipset | Intel Q470E |
|
|
||||||
+---------+---------------------------------------------------------------+
|
|
||||||
| SuperIO | Fintek F81966 |
|
|
||||||
+---------+---------------------------------------------------------------+
|
|
||||||
| TPM | Infineon SLB 9670VQ2.0 |
|
|
||||||
+---------+---------------------------------------------------------------+
|
|
||||||
| Boot | USB, SATA, NVMe |
|
|
||||||
+---------+---------------------------------------------------------------+
|
|
||||||
| Power | | Laptop Power Supply: |
|
|
||||||
| | | - 12V DC-in (IMB-1222) |
|
|
||||||
| | | - 12V~28V DC-in (IMB-1222-WV) |
|
|
||||||
+---------+---------------------------------------------------------------+
|
|
||||||
```
|
|
||||||
|
|
||||||
```text
|
|
||||||
+--------------+ +---------------------------+ +---------------+
|
|
||||||
| eDP |------------------------| |----| DDR4 SODIMM |
|
|
||||||
+--------------+ | | +---------------+
|
|
||||||
+--------------+ +--------------+ | | +---------------+
|
|
||||||
| HDMI |----| ITE IT6563 |----| |----| DDR4 SODIMM |
|
|
||||||
+--------------+ +--------------+ | | +---------------+
|
|
||||||
+--------------+ | Intel 10th Gen |
|
|
||||||
| Display Port |------------------------| (Comet lake-S) |
|
|
||||||
+--------------+ | Core Processors |
|
|
||||||
+--------------+ | LGA-1200 |
|
|
||||||
| Display Port |------------------------| |
|
|
||||||
+--------------+ | |
|
|
||||||
+--------------+ +--------------+ | | +---------------+
|
|
||||||
| LVDS |----| CH7511B-BF |----| |----| PCIe Gen3 x16 |
|
|
||||||
+--------------+ +--------------+ +---------------------------+ +---------------+
|
|
||||||
|
|
|
||||||
|
|
|
||||||
+------------------+ +---------------------------+ +---------------+
|
|
||||||
| 4 x USB 3.2 Gen1 | | | | 2 x SATA |
|
|
||||||
| Connector |--------------------| |----| Connector |
|
|
||||||
+------------------+ | | +---------------+
|
|
||||||
+------------------+ | | +---------------+
|
|
||||||
| 2 x USB 3.2 Gen1 | | | | M.2 KeyM SATA |
|
|
||||||
| Header |--------------------| Intel Q470E PCH |----| PCIe Gen3x4 |
|
|
||||||
+------------------+ | | +---------------+
|
|
||||||
+--------------+ | | +---------------+
|
|
||||||
| 2 x USB 2.0 | | | | M.2 Key E |
|
|
||||||
| Header |------------------------| |----| PCIe Gen3 x1/ |
|
|
||||||
+--------------+ | | | CNVi/USB2.0 |
|
|
||||||
+--------------+ +--------------+ | | +---------------+
|
|
||||||
| RJ45 |----| I225LM/I225V |----| | +---------------+
|
|
||||||
+--------------+ +--------------+ | | | M.2 Key B |
|
|
||||||
+--------------+ +--------------+ | |----| PCIe Gen3 x1/ |
|
|
||||||
| RJ45 |----| I219LM |----| | | USB3.0/USB2.0 |
|
|
||||||
+--------------+ +--------------+ | | +---------------+
|
|
||||||
+--------------+ +--------------+ | | +---------------+
|
|
||||||
| Mic-in | | Realtek | | | | TPM INFINEON |
|
|
||||||
| Line-out |----| ALC887 |----| |----| SLB 9670VQ2.0 |
|
|
||||||
| SPDIF | +--------------+ | | +---------------+
|
|
||||||
+--------------+ | +---------------------------+
|
|
||||||
+--------------+ |
|
|
||||||
| ALC122 | | LPC
|
|
||||||
+--------------+ +--------------+
|
|
||||||
+-----------------------+ +--------------+ | | +------------+
|
|
||||||
| 2 x COM RS232/422/485 |---| ST3243E |---| Fintek |----| CPU FAN x1 |
|
|
||||||
+-----------------------+ +--------------+ | F81966 | +------------+
|
|
||||||
+-----------------------+ +--------------+ | SuperIO | +------------+
|
|
||||||
| 2 x COM RS232 |---| ST3243E |---| |----| NCT 3941SA |
|
|
||||||
+-----------------------+ +--------------+ +--------------+ +------------+
|
|
||||||
| |
|
|
||||||
+--------------+ +------------+
|
|
||||||
| 8 x GPIO | | CHA FAN x1 |
|
|
||||||
+--------------+ +------------+
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
This port was created without a schematic/boardview, reverse engineering only.
|
|
||||||
Feel free to make changes.
|
|
||||||
|
|
||||||
## Required proprietary blobs
|
|
||||||
|
|
||||||
To build full working image of coreboot, the following blobs are required:
|
|
||||||
|
|
||||||
```{eval-rst}
|
|
||||||
+-----------------+-------------------------------------------+-------------------------+
|
|
||||||
| Binary file | Apply | Required/Optional |
|
|
||||||
+=================+===========================================+=========================+
|
|
||||||
| FSP-M & FSP-S | | Intel Firmware Support Package 2.1 | Required |
|
|
||||||
| | | 10th Generation Intel® Core™ processors | |
|
|
||||||
| | | and chipsets (formerly Comet Lake) | |
|
|
||||||
+-----------------+-------------------------------------------+-------------------------+
|
|
||||||
| IFD | Intel Flash Descriptor | Required |
|
|
||||||
+-----------------+-------------------------------------------+-------------------------+
|
|
||||||
| ME | Intel Management Engine | Required |
|
|
||||||
+-----------------+-------------------------------------------+-------------------------+
|
|
||||||
| GBE | Gigabit Ethernet Configuration | | Optional |
|
|
||||||
| | | | (if LAN2 is enabled) |
|
|
||||||
+-----------------+-------------------------------------------+-------------------------+
|
|
||||||
```
|
|
||||||
|
|
||||||
### FSP
|
|
||||||
|
|
||||||
Intel company provides [Firmware Support Package (2.1)](../../soc/intel/fsp/index.md)
|
|
||||||
to initialize this generation silicon. Please see this
|
|
||||||
[document](../../soc/intel/code_development_model/code_development_model.md).
|
|
||||||
|
|
||||||
### IFD, ME, GBE
|
|
||||||
|
|
||||||
Use the [vendor's firmware] version 1.80 to extract the IFD, ME, GBE blobs from it, according to
|
|
||||||
the [Intel IFD Binary Extraction Tutorial](../../util/ifdtool/binary_extraction.md).
|
|
||||||
|
|
||||||
```bash
|
|
||||||
wget --tries=5 "https://web.archive.org/web/20250413105432/https://download.asrock.com/IPC/BIOS/IMB-1222(1.80)ROM.zip"
|
|
||||||
unzip "IMB-1222(1.80)ROM.zip"
|
|
||||||
ifdtool --platform cnl -x IM12221.80
|
|
||||||
File IM12221.80 is 33554432 bytes
|
|
||||||
flashregion_0_flashdescriptor.bin Flash Region 0 (Flash Descriptor): 00000000 - 00000fff
|
|
||||||
flashregion_2_intel_me.bin Flash Region 2 (Intel ME): 00003000 - 01002fff
|
|
||||||
flashregion_3_gbe.bin Flash Region 3 (GbE): 00001000 - 00002fff
|
|
||||||
```
|
|
||||||
|
|
||||||
## Building coreboot
|
|
||||||
|
|
||||||
The following commands will help quickly configure and build a project for this board:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
make distclean
|
|
||||||
touch .config
|
|
||||||
./util/scripts/config --enable VENDOR_ASROCK
|
|
||||||
./util/scripts/config --enable BOARD_ASROCK_IMB_1222
|
|
||||||
make olddefconfig
|
|
||||||
make
|
|
||||||
```
|
|
||||||
|
|
||||||
## Payloads
|
|
||||||
|
|
||||||
```{eval-rst}
|
|
||||||
+---------------+------+---------+-----------+
|
|
||||||
| OS / Payload | EDK2 | SeaBIOS | LinuxBoot |
|
|
||||||
+===============+======+=========+===========+
|
|
||||||
| Ubuntu 22.04 | V | V | V |
|
|
||||||
+---------------+------+---------+-----------+
|
|
||||||
| Ubuntu 24.04 | V | V | V |
|
|
||||||
+---------------+------+---------+-----------+
|
|
||||||
| Windows 10 | V | | |
|
|
||||||
+---------------+------+---------+-----------+
|
|
||||||
| Windows 11 | V | | |
|
|
||||||
+---------------+------+---------+-----------+
|
|
||||||
| Android 13 | | V | |
|
|
||||||
+---------------+------+---------+-----------+
|
|
||||||
```
|
|
||||||
|
|
||||||
- LinuxBoot/Linux as payload;
|
|
||||||
- SeaBIOS (1.16.3);
|
|
||||||
- edk2 [MrChromebox fork] (uefipayload_2408).
|
|
||||||
|
|
||||||
### Additional information
|
|
||||||
|
|
||||||
- Ubuntu 22.04 (Linux 6.5.0-15-generic);
|
|
||||||
- Ubuntu 24.04 (Linux 6.8.0-41-generic);
|
|
||||||
- Microsoft Windows 10 Pro (10.0.19045.4780, 22H2 2022);
|
|
||||||
- Microsoft Windows 11 Pro (10.0.26100.3194, 24H2 2024);
|
|
||||||
- Andoid 13, [Bliss OS] x86_64 (16.9.7, Linux 6.1.112-gloria-xanmod1).
|
|
||||||
|
|
||||||
## Flashing coreboot
|
|
||||||
|
|
||||||
```{eval-rst}
|
|
||||||
+---------------------+--------------------------+
|
|
||||||
| Type | Value |
|
|
||||||
+=====================+==========================+
|
|
||||||
| Socketed flash | yes |
|
|
||||||
+---------------------+--------------------------+
|
|
||||||
| Model | | W25Q256JV |
|
|
||||||
| | | MX25L25673G |
|
|
||||||
+---------------------+--------------------------+
|
|
||||||
| Size | 32 MiB |
|
|
||||||
+---------------------+--------------------------+
|
|
||||||
| Package | WSON-8 8x6 mm |
|
|
||||||
+---------------------+--------------------------+
|
|
||||||
| Write protection | chipset PRR |
|
|
||||||
+---------------------+--------------------------+
|
|
||||||
| Dual BIOS feature | no |
|
|
||||||
+---------------------+--------------------------+
|
|
||||||
| Internal flashing | after flashing coreboot |
|
|
||||||
+---------------------+--------------------------+
|
|
||||||
```
|
|
||||||
|
|
||||||
The SPI flash can be accessed using [flashrom]. By default, only the
|
|
||||||
BIOS region of the flash is writable:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
flashrom -p internal -N -w coreboot.rom --ifd -i bios
|
|
||||||
```
|
|
||||||
|
|
||||||
If you wish to change any other region, such as the Management Engine
|
|
||||||
or firmware descriptor, then an external programmer is required. More
|
|
||||||
information about this [here](../../tutorial/flashing_firmware/index.md).
|
|
||||||
|
|
||||||
## Working
|
|
||||||
|
|
||||||
- Dual Channel DDR4 2933/2666/2400 MHz;
|
|
||||||
- Intel UHD Graphics:
|
|
||||||
- DP (both);
|
|
||||||
- HDMI;
|
|
||||||
- VGA Option ROM;
|
|
||||||
- libgfxinit;
|
|
||||||
- GOP;
|
|
||||||
- PCIe x16 Slot (Gen3);
|
|
||||||
- SATA ports;
|
|
||||||
- USB 2.0 ports;
|
|
||||||
- USB 3.2 ports;
|
|
||||||
- M.2 Key-E 2230 slot for Wireless (PCIe x1, USB 2.0 and CNVi);
|
|
||||||
- M.2 Key-B 3042/3052 WWAN slot for 4G/5G modem (PCIe x1, USB 3.0);
|
|
||||||
- M.2 Key-M 2242/2260/2280 for SSD/NVMe (PCIE x4, SATA3);
|
|
||||||
- LAN1 Intel I225LM/I225V, 10/100/1000/2500 Mbps;
|
|
||||||
- LAN2 Intel I219LM, 10/100/1000 Mbps;
|
|
||||||
- Realtek ALC887 HD Audio (line-out, mic-in);
|
|
||||||
- COM 1/2/3/4 ports (Fintek f81966);
|
|
||||||
- onboard speaker;
|
|
||||||
- HWM/FANs control (Fintek f81966);
|
|
||||||
- S3 suspend and wake;
|
|
||||||
- TPM;
|
|
||||||
- disabling ME with me_cleaner [XutaxKamay fork] (v1.2-9-gf20532d).
|
|
||||||
|
|
||||||
## Unknown/untested
|
|
||||||
|
|
||||||
- eDP/LVDS (currently disabled);
|
|
||||||
- PCIe riser cards;
|
|
||||||
- SPDIF;
|
|
||||||
- SATA RAID.
|
|
||||||
|
|
||||||
[ASRock IMB-1222]: https://web.archive.org/web/20220924171403/https://www.asrockind.com/en-gb/IMB-1222
|
|
||||||
[vendor's firmware]: https://web.archive.org/web/20250413105432/https://download.asrock.com/IPC/BIOS/IMB-1222(1.80)ROM.zip
|
|
||||||
[flashrom]: https://flashrom.org/
|
|
||||||
[MrChromebox fork]: https://github.com/MrChromebox/edk2
|
|
||||||
[XutaxKamay fork]: https://github.com/XutaxKamay/me_cleaner
|
|
||||||
[Bliss OS]: https://blissos.org/
|
|
||||||
|
|
@ -14,7 +14,7 @@ and their GPU is [Sea Islands] (GCN2-based).
|
||||||
|
|
||||||
A10 Richland is recommended for the best performance and working IOMMU.
|
A10 Richland is recommended for the best performance and working IOMMU.
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| A88XM-E | |
|
| A88XM-E | |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -36,7 +36,7 @@ A10 Richland is recommended for the best performance and working IOMMU.
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------------+------------+
|
+---------------------+------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+=====================+============+
|
+=====================+============+
|
||||||
|
|
@ -162,7 +162,7 @@ Tested even with/without the Bolton and Hudson blobs.
|
||||||
|
|
||||||
[ASUS A88XM-E]: https://www.asus.com/Motherboards/A88XME/
|
[ASUS A88XM-E]: https://www.asus.com/Motherboards/A88XME/
|
||||||
[Board manual]: https://dlcdnets.asus.com/pub/ASUS/mb/SocketFM2/A88XM-E/E9125_A88XM-E.pdf
|
[Board manual]: https://dlcdnets.asus.com/pub/ASUS/mb/SocketFM2/A88XM-E/E9125_A88XM-E.pdf
|
||||||
[flashrom]: https://flashrom.org/
|
[flashrom]: https://flashrom.org/Flashrom
|
||||||
[GD25Q64]: http://www.elm-tech.com/ja/products/spi-flash-memory/gd25q64/gd25q64.pdf
|
[GD25Q64]: http://www.elm-tech.com/ja/products/spi-flash-memory/gd25q64/gd25q64.pdf
|
||||||
[Piledriver]: https://en.wikipedia.org/wiki/Piledriver_%28microarchitecture%29#APU_lines
|
[Piledriver]: https://en.wikipedia.org/wiki/Piledriver_%28microarchitecture%29#APU_lines
|
||||||
[Sea Islands]: https://en.wikipedia.org/wiki/Graphics_Core_Next#GCN_2nd_generation
|
[Sea Islands]: https://en.wikipedia.org/wiki/Graphics_Core_Next#GCN_2nd_generation
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ Both "Trinity" and "Richland" desktop processing units are working,
|
||||||
the CPU architecture in these CPUs/APUs is [Piledriver],
|
the CPU architecture in these CPUs/APUs is [Piledriver],
|
||||||
and their GPU is [TeraScale 3] (VLIW4-based).
|
and their GPU is [TeraScale 3] (VLIW4-based).
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| F2A85-M | |
|
| F2A85-M | |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -35,7 +35,7 @@ and their GPU is [TeraScale 3] (VLIW4-based).
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
```
|
```
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| F2A85-M LE | |
|
| F2A85-M LE | |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -55,7 +55,7 @@ and their GPU is [TeraScale 3] (VLIW4-based).
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
```
|
```
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| F2A85-M PRO | |
|
| F2A85-M PRO | |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -77,7 +77,7 @@ and their GPU is [TeraScale 3] (VLIW4-based).
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------------+------------+
|
+---------------------+------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+=====================+============+
|
+=====================+============+
|
||||||
|
|
@ -192,7 +192,7 @@ This version is usable for all the GPUs.
|
||||||
|
|
||||||
[ASUS F2A85-M]: https://web.archive.org/web/20160320065008/http://www.asus.com/Motherboards/F2A85M/
|
[ASUS F2A85-M]: https://web.archive.org/web/20160320065008/http://www.asus.com/Motherboards/F2A85M/
|
||||||
[Board manual]: https://web.archive.org/web/20211028063105/https://dlcdnets.asus.com/pub/ASUS/mb/SocketFM2/F2A85-M/E8005_F2A85-M.pdf
|
[Board manual]: https://web.archive.org/web/20211028063105/https://dlcdnets.asus.com/pub/ASUS/mb/SocketFM2/F2A85-M/E8005_F2A85-M.pdf
|
||||||
[flashrom]: https://flashrom.org/
|
[flashrom]: https://flashrom.org/Flashrom
|
||||||
[Piledriver]: https://en.wikipedia.org/wiki/Piledriver_%28microarchitecture%29#APU_lines
|
[Piledriver]: https://en.wikipedia.org/wiki/Piledriver_%28microarchitecture%29#APU_lines
|
||||||
[TeraScale 3]: https://en.wikipedia.org/wiki/TeraScale_%28microarchitecture%29#TeraScale_3
|
[TeraScale 3]: https://en.wikipedia.org/wiki/TeraScale_%28microarchitecture%29#TeraScale_3
|
||||||
[W25Q64FV]: https://web.archive.org/web/20220127184640/https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf
|
[W25Q64FV]: https://web.archive.org/web/20220127184640/https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf
|
||||||
|
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
# ASUS PRIME H610i-PLUS
|
|
||||||
This is a Mini-ITX LGA1700 (Alder Lake/Raptor Lake) motherboard, using the H610 chipset and
|
|
||||||
DDR4 RAM. It's a close relative of the H610M-K, and like it is also sold in DDR4 and DDR5
|
|
||||||
variants.
|
|
||||||
|
|
||||||
## Variants
|
|
||||||
- *ASUS PRIME H610i-PLUS **D4***: uses DDR4 RAM, supported
|
|
||||||
- *ASUS PRIME H610i-PLUS* (no "D4"): uses DDR5 RAM, not currently supported by this port
|
|
||||||
|
|
||||||
## Flashing
|
|
||||||
This mainboard uses a standard 3.3V SOIC-8 SPI flash chip. The vendor firmware enables write
|
|
||||||
protection, thus for initial installation an external programmer is required. Thereafter,
|
|
||||||
coreboot can be updated internally using `flashrom -p internal`.
|
|
||||||
|
|
||||||
An external programmer can be connected using an ordinary chip clip, but for development or
|
|
||||||
testing, it can be more convenient to flash via the TPM header. A pinout can be found on Page
|
|
||||||
1-4 of the board's User's Manual - to select the flash chip, connect your CS line to
|
|
||||||
F_SPI_CS0#_R. An adapter cable can be made using a 2x7-pin 2.0mm female header, or a set of
|
|
||||||
2.0mm jumper wires. Beware, despite its similar appearance, this TPM header pinout is NOT
|
|
||||||
compatible with the pinout found on the MSI Z690A and Z790P boards (adapters for flashing those
|
|
||||||
boards over the SPI TPM header will not work on ASUS boards).
|
|
||||||
|
|
||||||
## Feature Support
|
|
||||||
### Working:
|
|
||||||
- Console over onboard serial port
|
|
||||||
- PS/2 keyboard
|
|
||||||
- Port 80 POST codes over ASUS debug header
|
|
||||||
- All USB ports, including USB3 working, except front USB2
|
|
||||||
- All outputs (DP, HDMI, VGA) for iGPU
|
|
||||||
- M.2 slot
|
|
||||||
- PCIe WiFi card in WiFi slot
|
|
||||||
- Onboard Ethernet
|
|
||||||
- PCIe ASPM and clock power management for all devices
|
|
||||||
- x16 PCIe slot
|
|
||||||
- All SATA ports
|
|
||||||
- Hard drive indicator LED
|
|
||||||
- All audio including front panel
|
|
||||||
- Fan control
|
|
||||||
- ME disable with HAP bit in IFD
|
|
||||||
- HSPHY-in-FMAP when ME is disabled
|
|
||||||
|
|
||||||
### Untested:
|
|
||||||
- CNVi WiFi card in WiFi slot
|
|
||||||
- SPI TPM
|
|
||||||
- Front USB2 ports (did not have an adapter on hand to test)
|
|
||||||
- Status LEDs in actual error states (they do show a normal status normally)
|
|
||||||
|
|
||||||
### Not working:
|
|
||||||
- S3 sleep
|
|
||||||
|
|
@ -10,7 +10,7 @@ This page describes how to run coreboot on the ASUS P2B-LS mainboard.
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------------+---------------------------+
|
+---------------------+---------------------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+=====================+===========================+
|
+=====================+===========================+
|
||||||
|
|
@ -90,7 +90,7 @@ for only CPU models that the board will actually be run with.
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| Northbridge | Intel I440BX |
|
| Northbridge | Intel I440BX |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -105,4 +105,4 @@ for only CPU models that the board will actually be run with.
|
||||||
|
|
||||||
## Extra resources
|
## Extra resources
|
||||||
|
|
||||||
[flashrom]: https://flashrom.org/
|
[flashrom]: https://flashrom.org/Flashrom
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ This page describes how to run coreboot on the ASUS P3B-F mainboard.
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------------+---------------------------+
|
+---------------------+---------------------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+=====================+===========================+
|
+=====================+===========================+
|
||||||
|
|
@ -88,7 +88,7 @@ for only CPU models that the board will actually be run with.
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| Northbridge | Intel I440BX |
|
| Northbridge | Intel I440BX |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -103,4 +103,4 @@ for only CPU models that the board will actually be run with.
|
||||||
|
|
||||||
## Extra resources
|
## Extra resources
|
||||||
|
|
||||||
[flashrom]: https://flashrom.org/
|
[flashrom]: https://flashrom.org/Flashrom
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ This page describes how to run coreboot on the [ASUS P5Q] desktop board.
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+-------------------+----------------+
|
+-------------------+----------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+===================+================+
|
+===================+================+
|
||||||
|
|
@ -56,7 +56,7 @@ You can flash coreboot into your motherboard using [this guide].
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+---------------------------------------------------+
|
+------------------+---------------------------------------------------+
|
||||||
| Northbridge | Intel P45 (called x4x in coreboot code) |
|
| Northbridge | Intel P45 (called x4x in coreboot code) |
|
||||||
+------------------+---------------------------------------------------+
|
+------------------+---------------------------------------------------+
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ This page describes how to run coreboot on the [ASUS P8H77-V].
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------------+----------------+
|
+---------------------+----------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+=====================+================+
|
+=====================+================+
|
||||||
|
|
@ -69,7 +69,7 @@ flash externally.
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
|
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -91,4 +91,4 @@ flash externally.
|
||||||
|
|
||||||
[ASUS P8C WS]: https://www.asus.com/supportonly/p8c_ws/helpdesk_knowledge/
|
[ASUS P8C WS]: https://www.asus.com/supportonly/p8c_ws/helpdesk_knowledge/
|
||||||
[W25Q64FVA1Q]: https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf
|
[W25Q64FVA1Q]: https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf
|
||||||
[flashrom]: https://flashrom.org/
|
[flashrom]: https://flashrom.org/Flashrom
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ This page describes how to run coreboot on the [ASUS P8H61-M LX].
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------------+------------+
|
+---------------------+------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+=====================+============+
|
+=====================+============+
|
||||||
|
|
@ -84,7 +84,7 @@ region is not readable even by the host.
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
|
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -107,5 +107,5 @@ region is not readable even by the host.
|
||||||
|
|
||||||
[ASUS P8H61-M LX]: https://www.asus.com/Motherboards/P8H61M_LX/
|
[ASUS P8H61-M LX]: https://www.asus.com/Motherboards/P8H61M_LX/
|
||||||
[W25Q32BV]: https://web.archive.org/web/20211002141814/https://www.winbond.com/resource-files/w25q32bv_revi_100413_wo_automotive.pdf
|
[W25Q32BV]: https://web.archive.org/web/20211002141814/https://www.winbond.com/resource-files/w25q32bv_revi_100413_wo_automotive.pdf
|
||||||
[flashrom]: https://flashrom.org/
|
[flashrom]: https://flashrom.org/Flashrom
|
||||||
[Board manual]: http://dlcdnet.asus.com/pub/ASUS/mb/LGA1155/P8H61_M_LX/E6803_P8H61-M_LX.zip
|
[Board manual]: http://dlcdnet.asus.com/pub/ASUS/mb/LGA1155/P8H61_M_LX/E6803_P8H61-M_LX.zip
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ This page describes how to run coreboot on the [ASUS P8H61-M Pro].
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------------+------------+
|
+---------------------+------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+=====================+============+
|
+=====================+============+
|
||||||
|
|
@ -78,7 +78,7 @@ region is not readable even by the host.
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
|
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -100,4 +100,4 @@ region is not readable even by the host.
|
||||||
|
|
||||||
[ASUS P8H61-M Pro]: https://www.asus.com/Motherboards/P8H61M_Pro/
|
[ASUS P8H61-M Pro]: https://www.asus.com/Motherboards/P8H61M_Pro/
|
||||||
[W25Q32BV]: https://www.winbond.com/resource-files/w25q32bv_revi_100413_wo_automotive.pdf
|
[W25Q32BV]: https://www.winbond.com/resource-files/w25q32bv_revi_100413_wo_automotive.pdf
|
||||||
[flashrom]: https://flashrom.org/
|
[flashrom]: https://flashrom.org/Flashrom
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ This page describes how to run coreboot on the [ASUS P8H77-V].
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------------+----------------+
|
+---------------------+----------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+=====================+================+
|
+=====================+================+
|
||||||
|
|
@ -56,7 +56,7 @@ work. The flash chip is socketed, so it's easy to remove and reflash.
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
|
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -78,4 +78,4 @@ work. The flash chip is socketed, so it's easy to remove and reflash.
|
||||||
|
|
||||||
[ASUS P8H77-V]: https://www.asus.com/supportonly/p8h77v/helpdesk_knowledge/
|
[ASUS P8H77-V]: https://www.asus.com/supportonly/p8h77v/helpdesk_knowledge/
|
||||||
[W25Q64FVA1Q]: https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf
|
[W25Q64FVA1Q]: https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf
|
||||||
[flashrom]: https://flashrom.org/
|
[flashrom]: https://flashrom.org/Flashrom
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ This page describes how to run coreboot on the [ASUS P8Z77-M].
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------------+----------------+
|
+---------------------+----------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+=====================+================+
|
+=====================+================+
|
||||||
|
|
@ -35,119 +35,84 @@ The flash chip is socketed, so it's easy to remove and reflash.
|
||||||
## Working
|
## Working
|
||||||
|
|
||||||
- All USB2 ports (mouse, keyboard and thumb drive)
|
- All USB2 ports (mouse, keyboard and thumb drive)
|
||||||
- USB3 ports on rear (Boots Arch-based SystemRescue 6.0.3 off a Kingston DataTraveler G4 8GB)
|
- USB3 ports on rear (Boots SystemRescue 6.0.3 off a Kingston DataTraveler G4 8GB)
|
||||||
- Gigabit Ethernet (RTL8111F)
|
- Gigabit Ethernet (RTL8111F)
|
||||||
- SATA3, SATA2 (all ports, hot-swap not tested)
|
- SATA3, SATA2 (all ports, hot-swap not tested)
|
||||||
- CPU Temp sensors and hardware monitor (See [Known issues] below)
|
(Blue SATA2) (Blue SATA2) (White SATA3)
|
||||||
|
port 5 port 3 port 1
|
||||||
|
port 6 port 4 port 2
|
||||||
|
|
||||||
|
- CPU Temp sensors and hardware monitor (some values don't make sense)
|
||||||
- Native and MRC memory initialization
|
- Native and MRC memory initialization
|
||||||
(please see [RAM compatibility] below)
|
(please see [Native raminit compatibility] and [MRC memory compatibility])
|
||||||
|
|
||||||
- Integrated graphics with both libgfxinit and the Intel Video BIOS OpROM
|
- Integrated graphics with both libgfxinit and the Intel Video BIOS OpROM
|
||||||
(VGA/DVI-D/HDMI tested and working)
|
(VGA/DVI-D/HDMI tested and working)
|
||||||
- 16x PCIe GPU in PCIe-16x/4x slots (tested using nVidia Quadro 600 under SystemRescue 6.0.3)
|
- 16x PCIe GPU in PCIe-16x/4x slots (tested using nVidia Quadro 600 under SystemRescue 6.0.3
|
||||||
|
(Arch based))
|
||||||
- Serial port
|
- Serial port
|
||||||
- PCI slot
|
- PCI slot
|
||||||
- Rockwell HSF 56k PCI modem (detected, not function tested)
|
Rockwell HSF 56k PCI modem, Sound Blaster Live! CT4780 (cards detected, not function tested)
|
||||||
- Sound Blaster Live! CT4780 (detected, not function tested)
|
Promise SATA150 TX2plus (R/W OK to connected IDE hard drive, OpRom loaded, cannot boot from
|
||||||
- Promise SATA150 TX2plus (R/W OK to connected IDE hard drive, OpRom loaded, cannot boot from
|
|
||||||
SeaBIOS)
|
SeaBIOS)
|
||||||
- PCIe x1 slot
|
- S3 suspend from Linux
|
||||||
- MSI Herald-BE (Qualcomm NCM865 m.2 Wifi 7 module via PCIe-m.2 adaptor)
|
|
||||||
- LPC POST card manually wired to TPM header
|
|
||||||
- 2-channel analog audio (WAV playback by mplayer via back panel line out port)
|
- 2-channel analog audio (WAV playback by mplayer via back panel line out port)
|
||||||
- HDMI digital audio
|
|
||||||
- Windows 10 with libgfxinit high resolution framebuffer and VBT
|
- Windows 10 with libgfxinit high resolution framebuffer and VBT
|
||||||
- UEFI boot into Fedora 38 through 41 with edk2 payload (202306 mrchromebox fork)
|
|
||||||
- PS/2 keyboard (IBM Model M #1391401 & original Microsoft Natural) with edk2 payload
|
|
||||||
|
|
||||||
## Known issues
|
## Known issues
|
||||||
|
|
||||||
- If you use MRC raminit, the NVRAM variable gfx_uma_size may be ignored as IGP's UMA could
|
- If you use MRC raminit, the NVRAM variable gfx_uma_size may be ignored as IGP's UMA could
|
||||||
be reconfigured by the blob.
|
be reconfigured by the blob.
|
||||||
|
|
||||||
- Sometimes only half the memory is initialized, and/or at reduced speed. This is being
|
|
||||||
investigated.
|
|
||||||
|
|
||||||
- If SeaBIOS is used for payload with libgfxinit, it must be brought in via coreboot's config.
|
- If SeaBIOS is used for payload with libgfxinit, it must be brought in via coreboot's config.
|
||||||
Otherwise integrated graphics would fail with a black screen.
|
Otherwise integrated graphics would fail with a black screen.
|
||||||
|
|
||||||
- PCI POST card is not functional because the PCI bridge early init is not yet done.
|
- PCI POST card is not functional because the PCI bridge early init is not yet done.
|
||||||
|
|
||||||
- Although the black PCIEX16_2 slot can physically fit an x16 card, it only has physical
|
- The black PCIEX16_2 slot, although can physically fit an x16, only has physical contacts for
|
||||||
contacts for x8, and is electrically x4 only.
|
an x8, and is electrically an x4 only.
|
||||||
|
|
||||||
- PS/2 keyboard may not work with SeaBIOS payload.
|
|
||||||
|
|
||||||
- These lm_sensors configurations are needed for hardware monitor values to make sense:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
label in1 "+12V"
|
|
||||||
label in4 "+5V"
|
|
||||||
compute in1 @*12, @/12
|
|
||||||
compute in4 @*5, @/5
|
|
||||||
# ...
|
|
||||||
set temp1_type 4
|
|
||||||
set temp2_type 4
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## Untested
|
## Untested
|
||||||
|
|
||||||
- Wake-on-LAN
|
- Wake-on-LAN
|
||||||
- USB3 on header
|
- USB3 on header
|
||||||
- TPM module
|
- TPM header
|
||||||
- EHCI debugging (Debug port is on the 5-pin side of USB2_910 header)
|
- EHCI debugging (Debug port is on the 5-pin side of USB2_910 header)
|
||||||
- S/PDIF audio out
|
- HDMI and S/PDIF audio out
|
||||||
|
|
||||||
## Not working
|
## Not working
|
||||||
|
|
||||||
- PS/2 mouse (a patch has been submitted for review)
|
- PS/2 keyboard or mouse
|
||||||
- 4 and 6 channel analog audio out: Rear left and right audio is a muted
|
- 4 and 6 channel analog audio out: Rear left and right audio is a muted
|
||||||
copy of front left and right audio, and the other two channels are silent.
|
copy of front left and right audio, and the other two channels are silent.
|
||||||
|
|
||||||
## RAM compatibility
|
## Native (and MRC) raminit compatibility
|
||||||
|
|
||||||
### Native and MRC raminit:
|
|
||||||
|
|
||||||
- OCZ OCZ3G1600LVAM 2x2GB kit works at DDR3-1066 instead of DDR3-1600.
|
- OCZ OCZ3G1600LVAM 2x2GB kit works at DDR3-1066 instead of DDR3-1600.
|
||||||
|
|
||||||
|
- GSkill F3-1600C9D-16GRSL 2x8GB SODIMM kit on adapter boots, but is highly unstable
|
||||||
|
with obvious pattern of bit errors during memtest86+ runs.
|
||||||
|
|
||||||
- Samsung PC3-10600U 2x2GB kit works at full rated speed.
|
- Samsung PC3-10600U 2x2GB kit works at full rated speed.
|
||||||
- GSkill F3-1600C9D-16GRSL 2x8GB SODIMM kit on unbranded adapter works at full rated speed.
|
|
||||||
|
|
||||||
### MRC raminit:
|
|
||||||
|
|
||||||
- Corsair ValueSelect CMSO4GX3M1C1600C11 4GB SODIMM works at full rated speed
|
|
||||||
on an unbranded adapter.
|
|
||||||
- Samsung M471B5273DH0 4GB SODIMM on adapter works at full rated speed.
|
|
||||||
|
|
||||||
### Native raminit:
|
|
||||||
|
|
||||||
- Kingston KTH9600B-4G 2x4GB kit works at full rated speed.
|
- Kingston KTH9600B-4G 2x4GB kit works at full rated speed.
|
||||||
- Samsung M471B5273DH0 4GB SODIMM on adapter works only at DDR3-1066 if max_mem_clock_mhz
|
|
||||||
is reduced to 666, and only one module would be detected. It will completely fail to
|
|
||||||
train if max_mem_clock_mhz is set to 800.
|
|
||||||
- Corsair modules on channel 1 fails training and is unusable.
|
|
||||||
- Two Patriot PV316G160C9K 2x8GB kits in all slots work at full rated speed.
|
|
||||||
|
|
||||||
## Extra onboard buttons
|
## Extra onboard buttons
|
||||||
|
|
||||||
The board has two onboard buttons, each with a related LED nearby.
|
The board has two onboard buttons, and each has a related LED nearby.
|
||||||
|
What controls the LEDs and what the buttons control are unknown,
|
||||||
|
therefore they currently do nothing under coreboot.
|
||||||
|
|
||||||
- `BIOS_FLBK` / `FLBK_LED`:
|
- BIOS_FLBK
|
||||||
OEM firmware uses this button to facilitate a simple update mechanism
|
OEM firmware uses this button to facilitate a simple update mechanism
|
||||||
via a USB drive plugged into the bottom USB port of the USB/LAN stack.
|
via a USB drive plugged into the bottom USB port of the USB/LAN stack.
|
||||||
They are connected to a proprietary AI1314 microcontroller.
|
|
||||||
They currently do nothing under coreboot.
|
|
||||||
|
|
||||||
- `MemOK!` / `DRAM_LED`:
|
- MemOK!
|
||||||
OEM firmware uses this button for memory tuning related to overclocking.
|
OEM firmware uses this button for memory tuning related to overclocking.
|
||||||
They are connected to the NCT6779D super I/O chip.
|
|
||||||
Button is connected to pin 74, and currently do nothing under coreboot.
|
|
||||||
DRAM_LED is connected to GP07 pin. Active low. Since commit f7ed007298e0
|
|
||||||
coreboot lights it up during early boot similar to vendor firmware.
|
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
|
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -167,6 +132,6 @@ The board has two onboard buttons, each with a related LED nearby.
|
||||||
|
|
||||||
- [Flash chip datasheet][W25Q64FVA1Q]
|
- [Flash chip datasheet][W25Q64FVA1Q]
|
||||||
|
|
||||||
[ASUS P8Z77-M]: https://www.asus.com/supportonly/p8z77-m/helpdesk_manual/
|
[ASUS P8Z77-M]: https://www.asus.com/Motherboards/P8Z77M/
|
||||||
[W25Q64FVA1Q]: https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf
|
[W25Q64FVA1Q]: https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf
|
||||||
[flashrom]: https://flashrom.org/
|
[flashrom]: https://flashrom.org/Flashrom
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ This page describes how to run coreboot on the [ASUS P8Z77-M PRO]
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------------+----------------+
|
+---------------------+----------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+=====================+================+
|
+=====================+================+
|
||||||
|
|
@ -143,7 +143,7 @@ easy to remove and reflash.
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
|
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -165,4 +165,4 @@ easy to remove and reflash.
|
||||||
|
|
||||||
[ASUS P8Z77-M PRO]: https://www.asus.com/Motherboards/P8Z77M_PRO/
|
[ASUS P8Z77-M PRO]: https://www.asus.com/Motherboards/P8Z77M_PRO/
|
||||||
[W25Q64FVA1Q]: https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf
|
[W25Q64FVA1Q]: https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf
|
||||||
[flashrom]: https://flashrom.org/
|
[flashrom]: https://flashrom.org/Flashrom
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ This page describes how to run coreboot on the [ASUS P8Z77-V].
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------------+----------------+
|
+---------------------+----------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+=====================+================+
|
+=====================+================+
|
||||||
|
|
@ -86,7 +86,7 @@ See [Asus Wi-Fi Go! v1].
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
|
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -108,5 +108,5 @@ See [Asus Wi-Fi Go! v1].
|
||||||
|
|
||||||
[ASUS P8Z77-V]: https://www.asus.com/supportonly/p8z77v/helpdesk_knowledge/
|
[ASUS P8Z77-V]: https://www.asus.com/supportonly/p8z77v/helpdesk_knowledge/
|
||||||
[W25Q64FVA1Q]: https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf
|
[W25Q64FVA1Q]: https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf
|
||||||
[flashrom]: https://flashrom.org/
|
[flashrom]: https://flashrom.org/Flashrom
|
||||||
[Asus Wi-Fi Go! v1]: ./wifigo_v1.md
|
[Asus Wi-Fi Go! v1]: ./wifigo_v1.md
|
||||||
|
|
|
||||||
|
|
@ -1,258 +0,0 @@
|
||||||
# ASUS P8Z77-V LE PLUS
|
|
||||||
|
|
||||||
This page describes how to run coreboot on the [ASUS P8Z77-V LE PLUS].
|
|
||||||
|
|
||||||
## Flashing coreboot
|
|
||||||
|
|
||||||
```{eval-rst}
|
|
||||||
+---------------------+----------------+
|
|
||||||
| Type | Value |
|
|
||||||
+=====================+================+
|
|
||||||
| Socketed flash | yes |
|
|
||||||
+---------------------+----------------+
|
|
||||||
| Model | W25Q64FVA1Q |
|
|
||||||
+---------------------+----------------+
|
|
||||||
| Size | 8 MiB |
|
|
||||||
+---------------------+----------------+
|
|
||||||
| Package | DIP-8 |
|
|
||||||
+---------------------+----------------+
|
|
||||||
| Write protection | yes |
|
|
||||||
+---------------------+----------------+
|
|
||||||
| Dual BIOS feature | no |
|
|
||||||
+---------------------+----------------+
|
|
||||||
| Internal flashing | yes |
|
|
||||||
+---------------------+----------------+
|
|
||||||
```
|
|
||||||
|
|
||||||
### How to flash
|
|
||||||
|
|
||||||
The main SPI flash cannot be written because the vendor firmware disables BIOSWE
|
|
||||||
and enables BLE/SMM_BWP flags in BIOS_CNTL for their latest BIOSes. An external
|
|
||||||
programmer is required. You must flash standalone, flashing in-circuit doesn't
|
|
||||||
work. The flash chip is socketed, so it's easy to remove and reflash.
|
|
||||||
|
|
||||||
See page 2-2 of user's manual for flash chip location.
|
|
||||||
|
|
||||||
### Extra preparations for changing PCIe slot configuration
|
|
||||||
|
|
||||||
On vendor firmware, the black PCIEX16_3 slot can be configured as x2 or x4.
|
|
||||||
If set for x4, PCIEX1_1 and PCIEX1_2 are disabled.
|
|
||||||
|
|
||||||
Before flashing coreboot for the first time, decide how you want to use the PCIe slots.
|
|
||||||
If you want to be able to choose between using the two PCIEX1 slots and the PCIEX16_3 slot at
|
|
||||||
x4 bandwidth, you need to do some preparation, namely make two backups of the whole flash
|
|
||||||
chip, specifically the flash descriptor under both configurations.
|
|
||||||
|
|
||||||
Enter vendor UEFI setup and check the PCIEX16_3 (black) slot bandwidth setting. You'll back up
|
|
||||||
under this setting first. Once one backup is made, come back and change the setting
|
|
||||||
from x2 to x4 (or vice versa) and reboot once, then make the other backup.
|
|
||||||
|
|
||||||
With PCIEX16_3 (black) slot bandwidth at x2, run these commands:
|
|
||||||
```bash
|
|
||||||
flashrom -p internal -r pciex163_x2.bin
|
|
||||||
dd if=pciex163_x2.bin of=ifd-pciex163_x2.bin bs=4096 count=1
|
|
||||||
```
|
|
||||||
|
|
||||||
With PCIEX16_3 (black) slot bandwidth at x4, run these commands:
|
|
||||||
```bash
|
|
||||||
flashrom -p internal -r pciex163_x4.bin
|
|
||||||
dd if=pciex163_x4.bin of=ifd-pciex163_x4.bin bs=4096 count=1
|
|
||||||
```
|
|
||||||
(`dd` needs not be run as root.)
|
|
||||||
|
|
||||||
Save the shortened `ifd-pciex163_*.bin` files for when you want to change the configuration.
|
|
||||||
Keep one of the full backups as well.
|
|
||||||
|
|
||||||
See "PCIe config" section below for more details.
|
|
||||||
|
|
||||||
## Working
|
|
||||||
|
|
||||||
- Core i5-3570K and i7-3770K CPUs
|
|
||||||
- Corsair CMZ16GX3M2A1600C10 2x8GB memory kit
|
|
||||||
- SeaBIOS 1.16.3
|
|
||||||
- edk2 mrchromebox fork uefipayload_2501
|
|
||||||
- Kernel 6.12.7
|
|
||||||
- All USB2 ports (mouse, keyboard)
|
|
||||||
- All USB3 ports
|
|
||||||
- Z77 SATA ports (WD Blue SA510, Liteon LH-20A1L)
|
|
||||||
- nVidia 8800GT GPU in PCIEX16_1 slot running x16
|
|
||||||
- PCI slots (Sound Blaster Live! Value)
|
|
||||||
- RTL8111F LAN
|
|
||||||
- CPU temperature sensors and hardware monitor
|
|
||||||
(see [below](#hardware-monitoring-and-fan-speed-control))
|
|
||||||
- Integrated graphics with libgfxinit and VBT
|
|
||||||
(all ports tested and working)
|
|
||||||
- Both PCIe x1 slots when properly configured
|
|
||||||
(see [How to flash](#how-to-flash) above and [PCIe config](#pcie-config);
|
|
||||||
Atheros 928x miniPCIe Wifi on adapter & MSI Herald-BE Wifi7 adapter)
|
|
||||||
- PCIe x4 slot with Intel Octane H10 1TB NVMe at x2 mode
|
|
||||||
- Serial port
|
|
||||||
- PS/2 keyboard
|
|
||||||
- Analog 7.1 audio out the 3.5mm jacks on rear panel
|
|
||||||
- Front HDA audio panel
|
|
||||||
- Digital audio out (Optical, internal SPDIF header, HDMI, DisplayPort)
|
|
||||||
|
|
||||||
Although a `spdif_dest` option is provided for feature parity with vendor firmware,
|
|
||||||
it doesn't seem to matter and digital audio out is available through all ports.
|
|
||||||
It does, however, change how the ports are presented to the OS.
|
|
||||||
|
|
||||||
- S3 suspend from Linux
|
|
||||||
|
|
||||||
## Known issues
|
|
||||||
|
|
||||||
- For 7.1 analog audio to work, at least the front channel (green jack) must be connected.
|
|
||||||
|
|
||||||
## Untested
|
|
||||||
|
|
||||||
- Hotplug of Z77 SATA ports
|
|
||||||
- EHCI debugging
|
|
||||||
|
|
||||||
## Not working
|
|
||||||
|
|
||||||
- Wake-on-LAN
|
|
||||||
- PS/2 mouse (requires a patch currently under review)
|
|
||||||
- Asmedia USB 3.0 battery charging support (for USB 3 ports on the LAN stack)
|
|
||||||
- USB Charger+ (When the bottom USB 3 port on the eSATA stack, also used for BIOS flashback,
|
|
||||||
remains powered while the rest of the system is off. Both features are controlled by the same
|
|
||||||
AI1314 controller.)
|
|
||||||
- Marvell SATA ports are brought up in IDE mode, pata_marvell driver is loaded,
|
|
||||||
but are effectively unusable.
|
|
||||||
|
|
||||||
## PCIe config
|
|
||||||
See [Extra preparations](#extra-preparations-for-changing-pcie-slot-configuration) section above.
|
|
||||||
|
|
||||||
Changing the PCIe slot configuration requires manipulating a PCH GPIO line and a soft strap in
|
|
||||||
the flash chip's descriptor section, which is read-only at runtime. coreboot programs the GPIO
|
|
||||||
to match the soft strap, but how it can update the soft strap itself is to be determined. Until
|
|
||||||
then, to make this change you have to re-flash the descriptor yourself, with one of the two
|
|
||||||
copies you previously saved per above:
|
|
||||||
```bash
|
|
||||||
flashrom -p internal --ifd -i fd -w ifd-pciex163_x2.bin
|
|
||||||
```
|
|
||||||
|
|
||||||
## Hardware monitoring and fan speed control
|
|
||||||
|
|
||||||
Although all fan ports are 4-pin for PWM fans, only CPU_FAN has actual PWM control;
|
|
||||||
all other fan speed control is by voltage only.
|
|
||||||
|
|
||||||
Write 1 into `/sys/class/hwmon/hwmon1/pwm1_mode` to enable CHA_FAN1 control, otherwise it
|
|
||||||
runs at full speed.
|
|
||||||
|
|
||||||
`fan5`/`pwm5` is not implemented and should be ignored.
|
|
||||||
|
|
||||||
These are the sensors.conf settings for this board:
|
|
||||||
|
|
||||||
```
|
|
||||||
label fan1 "CHA_FAN1"
|
|
||||||
label fan2 "CPU_FAN"
|
|
||||||
label fan3 "CHA_FAN2"
|
|
||||||
label fan4 "CHA_FAN3"
|
|
||||||
ignore fan5
|
|
||||||
label in1 "+12V"
|
|
||||||
label in4 "+5V"
|
|
||||||
compute in1 @*12, @/12
|
|
||||||
compute in4 @*5, @/5
|
|
||||||
set temp1_type 4
|
|
||||||
set temp2_type 4
|
|
||||||
```
|
|
||||||
|
|
||||||
## Extra onboard switches and LEDs
|
|
||||||
|
|
||||||
- `BIOS_FLBK`:
|
|
||||||
Vendor firmware uses this button to facilitate a simple update mechanism
|
|
||||||
via a USB drive plugged into the bottom USB port of the USB/ESATA6G stack.
|
|
||||||
It connects to the proprietary AI1314 controller, along with `FLBK_LED`.
|
|
||||||
|
|
||||||
- `MemOK!`:
|
|
||||||
OEM firmware uses this button for memory tuning related to overclocking.
|
|
||||||
It connects to pin 74 of super I/O.
|
|
||||||
|
|
||||||
- `DRAM_LED` lights up when there is a memory problem or when vendor MemOK! feature is
|
|
||||||
operating. Connects to GP07 line of super I/O. coreboot lights it up during memory init
|
|
||||||
similar to vendor firmware.
|
|
||||||
|
|
||||||
- `EPU`: When enabled, lights up `EPU_LED` and takes PCH GPIO44 low.
|
|
||||||
- `TPU`: When enabled, lights up `TPU_LED` and takes PCH GPIO45 low.
|
|
||||||
|
|
||||||
`EPU` and `TPU` are cues to vendor firmware to enable two embedded controllers for
|
|
||||||
overclocking features. coreboot is not yet able to make use of these two signals.
|
|
||||||
|
|
||||||
- `SB_PWR` lights up whenever board is receiving power. It's all hardware
|
|
||||||
and does not concern coreboot.
|
|
||||||
|
|
||||||
- `DRCT` is an undocumented 2-pin header next to the front panel connector block. It
|
|
||||||
connects to both the power button circuit and Z77's intruder detection input. Shorting this
|
|
||||||
header triggers both. With coreboot it currently works the same as the power button.
|
|
||||||
|
|
||||||
## Extra exposed GPIOs at `TB_HEADER`
|
|
||||||
|
|
||||||
A number of GPIO lines are broken out to `TB_HEADER` to support the ThunderboltEX adapter,
|
|
||||||
which never took off. Now they're yours to play with. Additional programming may be required such
|
|
||||||
as enabling GPIO by I/O for maximum effect.
|
|
||||||
|
|
||||||
This may be safely ignored for most normal uses.
|
|
||||||
|
|
||||||
**Be careful not to apply more than 3.3v to these pins!** And do not touch the two pins
|
|
||||||
labeled "NOT A GPIO".
|
|
||||||
|
|
||||||
Pinout:
|
|
||||||
```
|
|
||||||
+---+---+---+---+---+
|
|
||||||
| 2 | 4 | 5 | 7 | 9 |
|
|
||||||
+---+---+---+---+---+
|
|
||||||
| 1 | 3 | | 6 | 8 |
|
|
||||||
+---+---+---+---+---+
|
|
||||||
```
|
|
||||||
|
|
||||||
```{eval-rst}
|
|
||||||
+-----+-----------------------+----------+--------+
|
|
||||||
| Pin | Name | Source | GPIO # |
|
|
||||||
+=====+=======================+==========+========+
|
|
||||||
| 1 | S_DP_DDC_CLK_TO_TB | **NOT A GPIO** |
|
|
||||||
+-----+-----------------------+----------+--------+
|
|
||||||
| 2 | TB_GPIO_6 | NCT6779D | 14 |
|
|
||||||
+-----+-----------------------+----------+--------+
|
|
||||||
| 3 | S_DP_DDC_DATA_TO_TB | **NOT A GPIO** |
|
|
||||||
+-----+-----------------------+----------+--------+
|
|
||||||
| 4 | TB_GPIO_7 | NCT6779D | 13 |
|
|
||||||
+-----+-----------------------+----------+--------+
|
|
||||||
| 5 | TB_FWUPDATE | NCT6779D | 11 |
|
|
||||||
+-----+-----------------------+----------+--------+
|
|
||||||
| 6 | TB_DEV_HPD | Z77 | 0 |
|
|
||||||
+-----+-----------------------+----------+--------+
|
|
||||||
| 7 | TB_GO2SX | NCT6779D | 17 |
|
|
||||||
+-----+-----------------------+----------+--------+
|
|
||||||
| 8 | TB_GO2SX#_ACK | NCT6779D | 16 |
|
|
||||||
+-----+-----------------------+----------+--------+
|
|
||||||
| 9 | Not connected |
|
|
||||||
+-----+-------------------------------------------+
|
|
||||||
```
|
|
||||||
|
|
||||||
Pins 2, 4, 6, 8 have 1M ohm pulldowns.
|
|
||||||
|
|
||||||
## Technology
|
|
||||||
|
|
||||||
```{eval-rst}
|
|
||||||
+------------------+--------------------------------------------------+
|
|
||||||
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
|
|
||||||
+------------------+--------------------------------------------------+
|
|
||||||
| Southbridge | bd82x6x |
|
|
||||||
+------------------+--------------------------------------------------+
|
|
||||||
| CPU | model_206ax |
|
|
||||||
+------------------+--------------------------------------------------+
|
|
||||||
| Super I/O | Nuvoton NCT6779D |
|
|
||||||
+------------------+--------------------------------------------------+
|
|
||||||
| EC | TPU (ENE KB3722), AI1314 |
|
|
||||||
+------------------+--------------------------------------------------+
|
|
||||||
| Coprocessor | Intel Management Engine |
|
|
||||||
+------------------+--------------------------------------------------+
|
|
||||||
```
|
|
||||||
|
|
||||||
## Extra resources
|
|
||||||
|
|
||||||
- [Flash chip datasheet][W25Q64FVA1Q]
|
|
||||||
|
|
||||||
[ASUS P8Z77-V LE PLUS]: https://www.asus.com/supportonly/p8z77-v%20le%20plus/helpdesk_manual/
|
|
||||||
[W25Q64FVA1Q]: https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf
|
|
||||||
[flashrom]: https://flashrom.org/
|
|
||||||
[rtnicpg]: https://github.com/redchenjs/rtnicpg
|
|
||||||
|
|
@ -8,7 +8,7 @@ through a proprietary 16-1 pin connector.
|
||||||
I managed to grope the most pinout of the proprietary connector.
|
I managed to grope the most pinout of the proprietary connector.
|
||||||
See [Mini PCIe pinout] for more info.
|
See [Mini PCIe pinout] for more info.
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------+----------+-----------+------------+----------+-----------+
|
+------------+----------+-----------+------------+----------+-----------+
|
||||||
| WIFIGO Pin | Usage | mPCIe pin | WIFIGO Pin | Usage | mPCIe pin |
|
| WIFIGO Pin | Usage | mPCIe pin | WIFIGO Pin | Usage | mPCIe pin |
|
||||||
+============+==========+===========+============+==========+===========+
|
+============+==========+===========+============+==========+===========+
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------------+----------------+
|
+---------------------+----------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+=====================+================+
|
+=====================+================+
|
||||||
|
|
@ -58,7 +58,7 @@
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------+----------------------------------------+
|
+---------------+----------------------------------------+
|
||||||
| SoC | :doc:`../../soc/cavium/cn81xx/index` |
|
| SoC | :doc:`../../soc/cavium/cn81xx/index` |
|
||||||
+---------------+----------------------------------------+
|
+---------------+----------------------------------------+
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
## Hardware
|
## Hardware
|
||||||
### Technology
|
### Technology
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------+
|
+------------------+--------------------------------+
|
||||||
| CPU | Intel i7-8550U |
|
| CPU | Intel i7-8550U |
|
||||||
+------------------+--------------------------------+
|
+------------------+--------------------------------+
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
```
|
```
|
||||||
|
|
||||||
### Flash chip
|
### Flash chip
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------------+-----------------+
|
+---------------------+-----------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+=====================+=================+
|
+=====================+=================+
|
||||||
|
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
# Dell Latitude E7240
|
|
||||||
|
|
||||||
This page is about the notebook [Dell Latitude E7240].
|
|
||||||
|
|
||||||
## Release status
|
|
||||||
|
|
||||||
Dell Latitude E7240 was released in 2013 and is now end of life.
|
|
||||||
It can be bought from a secondhand market like Taobao or eBay.
|
|
||||||
|
|
||||||
## Required proprietary blobs
|
|
||||||
|
|
||||||
The following blobs are required to operate the hardware:
|
|
||||||
1. mrc.bin
|
|
||||||
2. Intel ME firmware
|
|
||||||
|
|
||||||
Memory reference code in mrc.bin is used to initialize the Haswell platform.
|
|
||||||
You need this blob to build a working coreboot image. Please read
|
|
||||||
[mrc.bin](../../northbridge/intel/haswell/mrc.bin) for instructions on
|
|
||||||
retrieving and using it.
|
|
||||||
|
|
||||||
Intel ME firmware is in the flash chip. It is not needed when building coreboot.
|
|
||||||
It can be extracted from the OEM firmware. You can also flash only the BIOS
|
|
||||||
region to leave Intel ME firmware untouched.
|
|
||||||
|
|
||||||
## Programming
|
|
||||||
|
|
||||||
The laptop can be flashed internally under OEM firmware using [dell-flash-unlock].
|
|
||||||
|
|
||||||
To flash with an external programmer, you need to remove the battery and the base cover.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
For more details have a look at the general [flashing tutorial].
|
|
||||||
|
|
||||||
It is also possible to flash internally under coreboot.
|
|
||||||
|
|
||||||
## Debugging
|
|
||||||
|
|
||||||
The board can be debugged with EHCI debug. The EHCI debug port is next to the miniDP port.
|
|
||||||
|
|
||||||
There's a serial port on dock, but it's not yet supported in coreboot.
|
|
||||||
|
|
||||||
Schematic of this laptop can be found online. The board name is Compal LA-9431P.
|
|
||||||
|
|
||||||
## Test status
|
|
||||||
|
|
||||||
### Not working
|
|
||||||
|
|
||||||
- EC ACPI
|
|
||||||
- SD/MMC card reader (kernel reports "Timeout waiting for hardware cmd interrupt.")
|
|
||||||
- No internal display before booting to OS when connected with a dock
|
|
||||||
|
|
||||||
### Working
|
|
||||||
|
|
||||||
- Integrated graphics init with libgfxinit
|
|
||||||
- mSATA
|
|
||||||
- WLAN
|
|
||||||
- USB
|
|
||||||
- Keyboard
|
|
||||||
- Touchpad and the buttons on it
|
|
||||||
- Dock: all USB ports, DisplayPort, eSATA
|
|
||||||
- Internal flashing
|
|
||||||
|
|
||||||
|
|
||||||
## Technology
|
|
||||||
|
|
||||||
```{eval-rst}
|
|
||||||
+------------------+-----------------------------+
|
|
||||||
| CPU | Intel Haswell-ULT |
|
|
||||||
+------------------+-----------------------------+
|
|
||||||
| PCH | Intel Lynx Point Low Power |
|
|
||||||
+------------------+-----------------------------+
|
|
||||||
| EC | SMSC MEC5075 |
|
|
||||||
+------------------+-----------------------------+
|
|
||||||
| Super I/O | SMSC ECE5048 |
|
|
||||||
+------------------+-----------------------------+
|
|
||||||
| Coprocessor | Intel Management Engine |
|
|
||||||
+------------------+-----------------------------+
|
|
||||||
```
|
|
||||||
|
|
||||||
[Dell Latitude E7240]: https://www.dell.com/support/home/en-us/product-support/product/latitude-e7240-ultrabook/docs
|
|
||||||
[dell-flash-unlock]: https://github.com/nic3-14159/dell-flash-unlock
|
|
||||||
[flashing tutorial]: ../../tutorial/flashing_firmware/ext_power.md
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 97 KiB |
|
|
@ -6,7 +6,7 @@ This page describes how to run coreboot on Dell OptiPlex 9010 SFF.
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------+---------------------------------------------------------------+
|
+------------+---------------------------------------------------------------+
|
||||||
| CPU | Intel Core 2nd Gen (Sandybridge) or 3rd Gen (Ivybridge) |
|
| CPU | Intel Core 2nd Gen (Sandybridge) or 3rd Gen (Ivybridge) |
|
||||||
+------------+---------------------------------------------------------------+
|
+------------+---------------------------------------------------------------+
|
||||||
|
|
@ -28,7 +28,7 @@ More specifications on [Dell OptiPlex 9010 specifications].
|
||||||
|
|
||||||
## Required proprietary blobs
|
## Required proprietary blobs
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+---------------------------------+---------------------+
|
+------------------+---------------------------------+---------------------+
|
||||||
| Binary file | Apply | Required / Optional |
|
| Binary file | Apply | Required / Optional |
|
||||||
+==================+=================================+=====================+
|
+==================+=================================+=====================+
|
||||||
|
|
@ -50,7 +50,7 @@ signature `SMSCUBIM`. The easiest way to do this is to use [UEFITool] and
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------------+--------------------------+
|
+---------------------+--------------------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+=====================+==========================+
|
+=====================+==========================+
|
||||||
|
|
@ -142,6 +142,6 @@ the cables or not being populated on the board case.
|
||||||
- Intruder detection
|
- Intruder detection
|
||||||
- Wake-on-Lan from ACPI S3
|
- Wake-on-Lan from ACPI S3
|
||||||
|
|
||||||
[flashrom]: https://flashrom.org/
|
[flashrom]: https://flashrom.org/Flashrom
|
||||||
[Dell OptiPlex 9010 specifications]: https://www.dell.com/downloads/global/products/optix/en/dell_optiplex_9010_spec_sheet.pdf
|
[Dell OptiPlex 9010 specifications]: https://www.dell.com/downloads/global/products/optix/en/dell_optiplex_9010_spec_sheet.pdf
|
||||||
[UEFITool]: https://github.com/LongSoft/UEFITool
|
[UEFITool]: https://github.com/LongSoft/UEFITool
|
||||||
|
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
# QEMU SBSA emulator
|
|
||||||
This page describes how to build and run ```coreboot``` for QEMU's sbsa-ref machine.
|
|
||||||
The qemu-sbsa ```coreboot``` image acts as BL-3.3 for Arm Trusted Firmware (```TF-A```) and
|
|
||||||
mainly takes care of setting up SMBIOS and ACPI tables, hence, in order to boot,
|
|
||||||
you also need to supply a ```TF-A``` image.
|
|
||||||
|
|
||||||
## Building TF-A
|
|
||||||
|
|
||||||
You can build ```TF-A``` from source by fetching
|
|
||||||
```
|
|
||||||
https://github.com/ARM-software/arm-trusted-firmware
|
|
||||||
```
|
|
||||||
and building the qemu-sbsa platform
|
|
||||||
```
|
|
||||||
PLAT=qemu_sbsa
|
|
||||||
```
|
|
||||||
Upon entry, ```coreboot``` expects a FDT pointer in x0, so make sure to compile ```TF-A``` with
|
|
||||||
```
|
|
||||||
ARM_LINUX_KERNEL_AS_BL33=1
|
|
||||||
```
|
|
||||||
This will force ```TF-A``` to pass a pointer to the FDT in x0.
|
|
||||||
|
|
||||||
## Building coreboot
|
|
||||||
|
|
||||||
Simply select the qemu-sbsa board and, optionally, configure a payload. We recommend
|
|
||||||
the ```leanefi``` payload. ```leanefi``` will setup a minimal set of UEFI services, just enough
|
|
||||||
to boot into a linux kernel.
|
|
||||||
|
|
||||||
## Running coreboot in QEMU
|
|
||||||
|
|
||||||
Once you have obtained ```TF-A``` and ```coreboot``` images, launch qemu via
|
|
||||||
|
|
||||||
```bash
|
|
||||||
qemu-system-aarch64 -nographic -m 1024 -M sbsa-ref -pflash <path/to/TFA.fd> \
|
|
||||||
-pflash <path/to/coreboot.rom>
|
|
||||||
```
|
|
||||||
|
|
||||||
## LBBR bootflow
|
|
||||||
|
|
||||||
arm and 9elements worked together in order to create a LBBR compliant bootflow
|
|
||||||
consisting of ```TF-A```, ```coreboot```, ```leanefi``` and ```LinuxBoot```. A proof of concept
|
|
||||||
can be found here <https://gitlab.arm.com/systemready/firmware-build/linuxboot/lbbr-coreboot-poc>
|
|
||||||
|
|
@ -1,182 +0,0 @@
|
||||||
# Erying Polestar G613 Pro
|
|
||||||
|
|
||||||
This page describes how to run coreboot on the [Erying Polestar G613 Pro].
|
|
||||||
|
|
||||||
## Required proprietary blobs
|
|
||||||
|
|
||||||
To build full working image of coreboot, the following blobs are required:
|
|
||||||
|
|
||||||
```{eval-rst}
|
|
||||||
+-----------------+---------------------------------+----------------------+
|
|
||||||
| Binary file | Apply | Required / Optional |
|
|
||||||
+=================+=================================+======================+
|
|
||||||
| Microcode | CPU Microcode | Required (see notes) |
|
|
||||||
+-----------------+---------------------------------+----------------------+
|
|
||||||
| FSP-M & FSP-S | Intel Firmware Support Package | Required |
|
|
||||||
+-----------------+---------------------------------+----------------------+
|
|
||||||
| ME | Intel Management Engine | Required (see notes) |
|
|
||||||
+-----------------+---------------------------------+----------------------+
|
|
||||||
| FD | Intel Flash Descriptor | Required (see notes) |
|
|
||||||
+-----------------+---------------------------------+----------------------+
|
|
||||||
```
|
|
||||||
|
|
||||||
Microcode for D0 stepping cannot be generated from the tree.
|
|
||||||
Therefore, including external microcode is **mandatory** for boards sold with
|
|
||||||
D0 stepping (Engineering Sample).
|
|
||||||
|
|
||||||
Maintainer of this port had included publicly-available [microcodes] in
|
|
||||||
`3rdparty/blobs` coreboot repository, which are being pulled as submodule.
|
|
||||||
|
|
||||||
Microcode binary for D0 stepping is called
|
|
||||||
`cpu806D0_platC2_ver00000054_2021-05-07_PRD_B0F9E245.bin`.
|
|
||||||
|
|
||||||
It should be selected by going to:
|
|
||||||
`Chipset -> Include CPU microcode in CBFS (Include external microcode binary)`.
|
|
||||||
|
|
||||||
Failure to choose an appropriate microcode will result in:
|
|
||||||
- MCE (Machine Check Exception) errors.
|
|
||||||
- Issues with APIC, resulting in random hangs.
|
|
||||||
- Unstable system RAM, leading to bit flips and data corruption.
|
|
||||||
|
|
||||||
There are no extra steps required for FSP.
|
|
||||||
Both SKUs work perfectly with FSP Intel publishes in their public repository.
|
|
||||||
coreboot automatically pulls FSP binary from `3rdparty/fsp` submodule
|
|
||||||
at build time, which points to TigerLakeFspBinPkg/Client package in
|
|
||||||
official Intel FSP repository.
|
|
||||||
|
|
||||||
## Flashing coreboot
|
|
||||||
|
|
||||||
### Internally
|
|
||||||
|
|
||||||
Vendor of this motherboard hasn't locked any flash regions, resulting in
|
|
||||||
[flashrom] having full access to the SPI chip.
|
|
||||||
Assuming that user had booted Linux with `iomem=relaxed`, they can:
|
|
||||||
- Flash coreboot from stock firmware
|
|
||||||
- Flash stock firmware from coreboot
|
|
||||||
- Update coreboot build to a newer version
|
|
||||||
|
|
||||||
Without opening the case and connecting the SPI flasher.
|
|
||||||
Please note that you will need to use [flashrom] v1.3.0 or newer,
|
|
||||||
as older versions won't detect the chipset.
|
|
||||||
|
|
||||||
If you're using [flashrom] or [flashprog] (fork of flashrom), you can
|
|
||||||
skip extracting `SI_BIOS` and `SI_ME` regions from your ROM, and flash
|
|
||||||
coreboot to `SI_BIOS` region by issuing the following command:
|
|
||||||
`flashrom -p internal --ifd -i SI_BIOS -w ./build/coreboot.rom`
|
|
||||||
|
|
||||||
### Externally
|
|
||||||
|
|
||||||
SPI chip on this mainboard is located right underneath the PCH heatsink.
|
|
||||||
Due to it's location, it's likely that you will need to move (or remove)
|
|
||||||
the PCH (Platform Controller Hub) heatsink in order to clip it properly.
|
|
||||||
|
|
||||||
Vendor populated this board with Winbond W25Q128FV chip in SOIC-8 package.
|
|
||||||
Although the stock chip is 16MiB, it is possible to replace it with 32MiB
|
|
||||||
equivalent if user desires to use LinuxBoot payload instead of EDK2.
|
|
||||||
|
|
||||||
Please note that SPI voltage on this board is standard 3.3V,
|
|
||||||
despite using mobile SoC and PCH.
|
|
||||||
|
|
||||||
## Tested and working
|
|
||||||
|
|
||||||
- RS232 serial output from IT8613E for debugging (cbmem, Linux)
|
|
||||||
- Fan control from userspace (IT8613E Environment Controller)
|
|
||||||
- USB2.0 and 3.0
|
|
||||||
- HDMI, DisplayPort (iGPU, including audio)
|
|
||||||
- Realtek RTL8111 (GbE NIC)
|
|
||||||
- Realtek ALC897 (integrated audio)
|
|
||||||
- PCIe x16 4.0 (SoC)
|
|
||||||
- PCIe x1 3.0 (PCH)
|
|
||||||
- M.2 x4 4.0 (SoC)
|
|
||||||
- M.2 x4 3.0 (PCH)
|
|
||||||
- M.2 NGFF (WiFi)
|
|
||||||
- 4x SATA3 ports
|
|
||||||
- IOMMU/VT-x (PCIe passthrough)
|
|
||||||
- PCIe ReBAR (Resizable BAR)
|
|
||||||
- Intel PTT (fTPM 2.0)
|
|
||||||
|
|
||||||
## Work in progress, broken, issues
|
|
||||||
|
|
||||||
- XMP Profiles (some people reported issues, despite successful tests).
|
|
||||||
You can enable it by setting `SpdProfileSelected` in `romstage_fsp_params.c`.
|
|
||||||
See [FSP XMP flags] for configuration options, proceed with caution.
|
|
||||||
- Sleep states (which were broken on stock as well, RAM loses power in S3).
|
|
||||||
- Automatic fan control (fans will always spin at 50% - see below).
|
|
||||||
- PCIe ASPM (results in AER spam in dmesg).
|
|
||||||
|
|
||||||
Please ensure to:
|
|
||||||
- Disable sleep state in your OS.
|
|
||||||
- Configure automatic fan control using pwmconfig
|
|
||||||
(`modprobe it87 force_id=0x8603`).
|
|
||||||
- Append `pcie_aspm=off` to your kernel commandline to avoid dmesg spam.
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
1. Required blobs, if flashing the entire flash chip.
|
|
||||||
They can be skipped safely if you are planning on flashing
|
|
||||||
only the `SI_BIOS` region.
|
|
||||||
- Intel Flash Descriptor (IFD): `fd.bin`
|
|
||||||
- Intel Management Engine (ME): `me.bin`
|
|
||||||
|
|
||||||
Both blobs included in `3rdparty/blobs` repository were extracted
|
|
||||||
from vendor's firmware (available to download on their website).
|
|
||||||
IFD region has been modified using `ifdtool` to set
|
|
||||||
`MeAltDisable` flag.
|
|
||||||
|
|
||||||
2. Modifications
|
|
||||||
|
|
||||||
It is possible to replace Winbond 16MB chip with 32MB equivalent,
|
|
||||||
which would allow you to use LinuxBoot or implement
|
|
||||||
RO + A/B VBOOT update scheme.
|
|
||||||
|
|
||||||
3. Payload and pre-OS display output
|
|
||||||
|
|
||||||
If you are using an external graphics card (AMD, Nvidia, Intel Arc),
|
|
||||||
you will see output in your OS as soon as kernel initializes the
|
|
||||||
card (called "modprobing" in Linux) regardless of payload you chose.
|
|
||||||
|
|
||||||
This board was tested with following payloads:
|
|
||||||
- EDK2
|
|
||||||
- U-Boot
|
|
||||||
- LinuxBoot (U-Root + Linux kernel)
|
|
||||||
|
|
||||||
If you're planning to primarly use an external card, disable iGPU by
|
|
||||||
enabling `Chipset -> Disable Integrated GFX Controller (0:2:0)`
|
|
||||||
and use [MrChromebox's EDK2] tree.
|
|
||||||
|
|
||||||
In order to enable loading Option ROMs from PCIe devices, enable:
|
|
||||||
`Payload -> Load and Execute OpROMs on PCIe devices`
|
|
||||||
|
|
||||||
This functionality has been tested with following graphics cards,
|
|
||||||
with following results:
|
|
||||||
- Nvidia GeForce RTX3080, RTX3090: Works perfectly.
|
|
||||||
- AMD Radeon RX6600XT, RX7800XT: Works, but requires
|
|
||||||
`Extend resource window for PCIe devices above 4G` if `Support PCIe
|
|
||||||
Resizable BARs` is enabled.
|
|
||||||
- Intel Arc A580: Works, but option
|
|
||||||
`Extend resource window for PCIe devices above 4G` is **mandatory**.
|
|
||||||
|
|
||||||
## Specification
|
|
||||||
|
|
||||||
```{eval-rst}
|
|
||||||
+------------------+------------------------------+
|
|
||||||
| SoC | Intel TigerLake Halo |
|
|
||||||
+------------------+------------------------------+
|
|
||||||
| PCH | Intel HM570 |
|
|
||||||
+------------------+------------------------------+
|
|
||||||
| Super I/O | ITE IT8613E |
|
|
||||||
+------------------+------------------------------+
|
|
||||||
| SPI | Winbond W25Q128FV 16MiB 3.3V |
|
|
||||||
+------------------+------------------------------+
|
|
||||||
| NIC | Realtek RTL8111 |
|
|
||||||
+------------------+------------------------------+
|
|
||||||
| Audio | Realtek ALC897 |
|
|
||||||
+------------------+------------------------------+
|
|
||||||
```
|
|
||||||
|
|
||||||
[Erying Polestar G613 Pro]: https://www.erying.cc/products-detail/id-97.html
|
|
||||||
[microcodes]: https://github.com/platomav/CPUMicrocodes/tree/master/Intel
|
|
||||||
[FSP XMP Flags]: https://github.com/intel/FSP/blob/master/TigerLakeFspBinPkg/Client/Include/FspmUpd.h#L586-L591
|
|
||||||
[MrChromebox's EDK2]: https://github.com/MrChromebox/edk2
|
|
||||||
[flashrom]: https://flashrom.org/
|
|
||||||
[flashprog]: https://flashprog.org/wiki/Flashprog
|
|
||||||
|
|
@ -63,7 +63,7 @@ Specifically, it's a Winbond W25Q64FV (3.3V), whose datasheet can be found
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| SoC | Intel Atom Processor N3710 |
|
| SoC | Intel Atom Processor N3710 |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -77,4 +77,4 @@ Specifically, it's a Winbond W25Q64FV (3.3V), whose datasheet can be found
|
||||||
|
|
||||||
[W25Q64FW]: https://www.winbond.com/resource-files/w25q64fw%20revn%2005182017%20sfdp.pdf
|
[W25Q64FW]: https://www.winbond.com/resource-files/w25q64fw%20revn%2005182017%20sfdp.pdf
|
||||||
[W25Q64FV]: https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf
|
[W25Q64FV]: https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf
|
||||||
[flashrom]: https://flashrom.org/
|
[flashrom]: https://flashrom.org/Flashrom
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ Intel company provides [Firmware Support Package (2.0)](../../soc/intel/fsp/inde
|
||||||
|
|
||||||
FSP Information:
|
FSP Information:
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+-----------------------------+-------------------+-------------------+
|
+-----------------------------+-------------------+-------------------+
|
||||||
| FSP Project Name | Directory | Specification |
|
| FSP Project Name | Directory | Specification |
|
||||||
+-----------------------------+-------------------+-------------------+
|
+-----------------------------+-------------------+-------------------+
|
||||||
|
|
@ -116,7 +116,7 @@ output.
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| SoC | Intel Kaby Lake U |
|
| SoC | Intel Kaby Lake U |
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
|
|
@ -130,4 +130,4 @@ output.
|
||||||
|
|
||||||
[W25Q128JVSIQ]: https://www.winbond.com/resource-files/w25q128jv%20revf%2003272018%20plus.pdf
|
[W25Q128JVSIQ]: https://www.winbond.com/resource-files/w25q128jv%20revf%2003272018%20plus.pdf
|
||||||
[W25Q128JVSIM]: https://www.winbond.com/resource-files/w25q128jv%20dtr%20revb%2011042016.pdf
|
[W25Q128JVSIM]: https://www.winbond.com/resource-files/w25q128jv%20dtr%20revb%2011042016.pdf
|
||||||
[flashrom]: https://flashrom.org/
|
[flashrom]: https://flashrom.org/Flashrom
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ The default options for this board should result in a fully working image:
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+---------------------+--------+
|
+---------------------+--------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+=====================+========+
|
+=====================+========+
|
||||||
|
|
@ -56,7 +56,7 @@ To do this gently take the SPI flash out of its socket and flash with your progr
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+------------------+
|
+------------------+------------------+
|
||||||
| Northbridge | Intel Pinevew |
|
| Northbridge | Intel Pinevew |
|
||||||
+------------------+------------------+
|
+------------------+------------------+
|
||||||
|
|
@ -72,4 +72,4 @@ To do this gently take the SPI flash out of its socket and flash with your progr
|
||||||
|
|
||||||
[FOXCONN D41S]: http://www.foxconnchannel.com/ProductDetail.aspx?T=motherboard&U=en-us0000481
|
[FOXCONN D41S]: http://www.foxconnchannel.com/ProductDetail.aspx?T=motherboard&U=en-us0000481
|
||||||
[FOXCONN]: http://www.foxconnchannel.com
|
[FOXCONN]: http://www.foxconnchannel.com
|
||||||
[Flashrom]: https://flashrom.org/
|
[Flashrom]: https://flashrom.org/Flashrom
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ This motherboard [also works with Libreboot](https://libreboot.org/docs/install/
|
||||||
|
|
||||||
## Technology
|
## Technology
|
||||||
|
|
||||||
```{eval-rst}
|
```eval_rst
|
||||||
+------------------+--------------------------------------------------+
|
+------------------+--------------------------------------------------+
|
||||||
| Type | Value |
|
| Type | Value |
|
||||||
+==================+==================================================+
|
+==================+==================================================+
|
||||||
|
|
@ -30,7 +30,9 @@ This motherboard [also works with Libreboot](https://libreboot.org/docs/install/
|
||||||
|
|
||||||
## Preparation
|
## Preparation
|
||||||
|
|
||||||
For more datails how to get sources and build the toolchain, see <project:../../tutorial/part1.md>.
|
```eval_rst
|
||||||
|
For more datails how to get sources and build the toolchain, see :doc:`../../tutorial/part1`.
|
||||||
|
```
|
||||||
|
|
||||||
### Devuan 4 Chimaera
|
### Devuan 4 Chimaera
|
||||||
|
|
||||||
|
|
@ -138,8 +140,10 @@ Built gigabyte/ga-g41m-es2l (GA-G41M-ES2L)
|
||||||
|
|
||||||
## Flashing coreboot
|
## Flashing coreboot
|
||||||
|
|
||||||
|
```eval_rst
|
||||||
In addition to the information here, please see the
|
In addition to the information here, please see the
|
||||||
<project:../../tutorial/flashing_firmware/index.md>.
|
:doc:`../../tutorial/flashing_firmware/index`.
|
||||||
|
```
|
||||||
|
|
||||||
### Do backup
|
### Do backup
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue