Compare commits

..

1 commit

Author SHA1 Message Date
Jeremy Compostella
2ff2409037 nb/intel/sandybridge: Fix unitialized variable issue
Cherry-picked from main branch using commit caa0c0e71a.

Original commit message:

commit 1e9601c5ef ("nb/intel/sandybridge: Standardize MRC vs. native
SPD mapping API") introduced an uninitialized variable issue.

Change-Id: I41b081dc4c961acc04423067e29e0eabe5f17539
Found-by: Coverity CID 1524317
Original-Signed-off-by: Jeremy Compostella <jeremy.compostella@intel.com>
Original-Reviewed-on: https://review.coreboot.org/c/coreboot/+/79093
Original-Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Original-Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Original-Reviewed-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Signed-off-by: Felix Singer <felixsinger@posteo.net>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/79231
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin L Roth <gaumless@gmail.com>
2023-11-23 23:29:19 +00:00
12189 changed files with 124643 additions and 1088077 deletions

View file

@ -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.
--no-tree

View file

@ -1,228 +1,21 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# clang-format configuration file. Intended for clang-format >= 16.
#
# For more information, see:
#
# https://clang.llvm.org/docs/ClangFormat.html
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
# https://clang-format-configurator.site/
#
---
Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignArrayOfStructures: Left
AlignConsecutiveAssignments:
Enabled: false
AcrossEmptyLines: false
AcrossComments: true
AlignCompound: false
PadOperators: true
AlignConsecutiveBitFields:
Enabled: true
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: true
AlignConsecutiveDeclarations:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: true
AlignConsecutiveMacros:
Enabled: true
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: true
AlignEscapedNewlines: Left
AlignOperands: Align
AlignTrailingComments:
Kind: Always
OverEmptyLines: 0
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
# git grep '^#define [^[:space:]]*__.*[^[:space:]]*__attribute__' | grep -v "vendorcode\|payloads\|util" | sed "s|.*:||;s|^#define \([^[:space:]]*__[^([:space:]]*\).*$| - '\1'|" | LC_ALL=C sort -u
AttributeMacros:
- '__aligned'
- '__always_inline'
- '__always_unused'
- '__cpu_driver'
- '__fallthrough'
- '__maybe_unused'
- '__must_check'
- '__noreturn'
- '__packed'
- '__pci_driver'
- '__printf'
- '__weak'
BinPackArguments: true
BinPackParameters: true
BitFieldColonSpacing: Both
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterExternBlock: false
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakAfterAttributes: Never
BreakAfterJavaFieldAnnotations: false
BreakArrays: false
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: Always
BreakBeforeBraces: Custom
BreakBeforeInlineASMColon: OnlyMultiline
BreakBeforeTernaryOperators: false
BreakConstructorInitializers: AfterColon
BreakInheritanceList: AfterColon
BreakStringLiterals: false
ColumnLimit: 96
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: false
# git grep '^#define [^[:space:]]*for_each[^[:space:]]*(' | grep -v "vendorcode\|payloads\|util" | sed "s|.*:||;s|^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$| - '\1'|" | LC_ALL=C sort -u
ForEachMacros:
- 'list_for_each'
# git grep -i '^#define \+if[^[:space:]]*(' | grep -v "vendorcode\|payloads\|util" | sed "s|.*:||;s|^#define \([^[:space:]]*if[^[:space:]]*\)(.*$| - '\1'|I" | grep -v IFIX | LC_ALL=C sort -u
IfMacros:
- 'IF_CHANNEL_POPULATED'
- 'IF_DIMM_POPULATED'
- 'IF_RANK_POPULATED'
- 'IfBit0'
IncludeBlocks: Preserve
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseBlocks: false
IndentCaseLabels: false
IndentExternBlock: AfterExternBlock
IndentGotoLabels: false
IndentPPDirectives: None
IndentRequiresClause: true
IndentWidth: 8
IndentWrappedFunctionNames: false
InsertBraces: false
InsertNewlineAtEOF: true
InsertTrailingCommas: None
IntegerLiteralSeparator:
Binary: 0
BinaryMinDigits: 0
Decimal: 0
DecimalMinDigits: 0
Hex: 0
HexMinDigits: 0
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
LambdaBodyIndentation: Signature
LineEnding: LF
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 8
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PackConstructorInitializers: BinPack
PenaltyBreakAssignment: 10
PenaltyBreakBeforeFirstCallParameter: 30
PenaltyBreakComment: 10
PenaltyBreakFirstLessLess: 0
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 10
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 100
PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
PPIndentWidth: -1
QualifierAlignment: Left
ReferenceAlignment: Pointer
ReflowComments: false
RemoveBracesLLVM: false
RemoveSemicolon: false
RequiresClausePosition: OwnLine
RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: Never
SortJavaStaticImport: Before
SortUsingDeclarations: Never
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatementsExceptControlMacros
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: false
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: false
AfterOverloadedOperator: false
AfterRequiresInClause: false
AfterRequiresInExpression: false
BeforeNonEmptyParentheses: false
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInConditionalStatement: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: 1
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: c++17
TabWidth: 8
UseTab: ForContinuationAndIndentation
...
BasedOnStyle: LLVM
Language: Cpp
IndentWidth: 8
UseTab: Always
BreakBeforeBraces: Linux
AllowShortIfStatementsOnASingleLine: false
IndentCaseLabels: false
SortIncludes: false
ContinuationIndentWidth: 8
ColumnLimit: 96
AlwaysBreakBeforeMultilineStrings: true
AllowShortLoopsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AlignEscapedNewlinesLeft: false
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: false
AlignAfterOpenBracket: true
SpaceAfterCStyleCast: false
MaxEmptyLinesToKeep: 2
BreakBeforeBinaryOperators: NonAssignment
BreakStringLiterals: false

View file

@ -9,7 +9,3 @@ charset = utf-8
insert_final_newline = true
end_of_line = lf
trim_trailing_whitespace = true
[*.sh]
indent_style = space
indent_size = 2

2
.gitignore vendored
View file

@ -9,7 +9,6 @@ defconfig
build/
coreboot-builds/
coreboot-builds*/
generated/
site-local
@ -35,7 +34,6 @@ tags
.cache
compile_commands.json
.vscode/
.clangd
# Cross-compile toolkits
xgcc/

51
.gitmodules vendored
View file

@ -1,81 +1,70 @@
[submodule "3rdparty/blobs"]
path = 3rdparty/blobs
url = https://review.coreboot.org/blobs.git
url = ../blobs.git
update = none
ignore = dirty
[submodule "util/nvidia-cbootimage"]
path = util/nvidia/cbootimage
url = https://review.coreboot.org/nvidia-cbootimage.git
url = ../nvidia-cbootimage.git
[submodule "vboot"]
path = 3rdparty/vboot
url = https://review.coreboot.org/vboot.git
url = ../vboot.git
branch = main
[submodule "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"]
path = 3rdparty/libhwbase
url = https://review.coreboot.org/libhwbase.git
url = ../libhwbase.git
[submodule "libgfxinit"]
path = 3rdparty/libgfxinit
url = https://review.coreboot.org/libgfxinit.git
url = ../libgfxinit.git
[submodule "3rdparty/fsp"]
path = 3rdparty/fsp
url = https://review.coreboot.org/fsp.git
url = ../fsp.git
update = none
ignore = dirty
[submodule "opensbi"]
path = 3rdparty/opensbi
url = https://review.coreboot.org/opensbi.git
url = ../opensbi.git
[submodule "intel-microcode"]
path = 3rdparty/intel-microcode
url = https://review.coreboot.org/intel-microcode.git
url = ../intel-microcode.git
update = none
ignore = dirty
branch = main
[submodule "3rdparty/ffs"]
path = 3rdparty/ffs
url = https://review.coreboot.org/ffs.git
url = ../ffs.git
[submodule "3rdparty/amd_blobs"]
path = 3rdparty/amd_blobs
url = https://review.coreboot.org/amd_blobs
url = ../amd_blobs
update = none
ignore = dirty
[submodule "3rdparty/cmocka"]
path = 3rdparty/cmocka
url = https://review.coreboot.org/cmocka.git
url = ../cmocka.git
update = none
branch = stable-1.1
[submodule "3rdparty/qc_blobs"]
path = 3rdparty/qc_blobs
url = https://review.coreboot.org/qc_blobs.git
url = ../qc_blobs.git
update = none
ignore = dirty
[submodule "3rdparty/intel-sec-tools"]
path = 3rdparty/intel-sec-tools
url = https://review.coreboot.org/9esec-security-tooling.git
ignore = dirty
url = ../9esec-security-tooling.git
[submodule "3rdparty/stm"]
path = 3rdparty/stm
url = https://review.coreboot.org/STM
url = ../STM
branch = stmpe
[submodule "util/goswid"]
path = util/goswid
url = https://review.coreboot.org/goswid
url = ../goswid
branch = trunk
ignore = dirty
[submodule "src/vendorcode/amd/opensil/genoa_poc/opensil"]
path = src/vendorcode/amd/opensil/genoa_poc/opensil
url = https://review.coreboot.org/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
url = ../opensil_genoa_poc.git

View file

@ -2,4 +2,4 @@
host=review.coreboot.org
port=29418
project=coreboot
defaultbranch=main
defaultbranch=master

2
3rdparty/amd_blobs vendored

@ -1 +1 @@
Subproject commit aa9288a33c6d7a67e55b8757390029207593fa9f
Subproject commit e4519efca74615f0f322d595afa7702c64753914

@ -1 +1 @@
Subproject commit 9109143417b24337d39a2a9583828a44996f8aac
Subproject commit 88b2d81345dfd84902aae586a743d00ac5df2f48

2
3rdparty/blobs vendored

@ -1 +1 @@
Subproject commit 4a8de0324e7d389454ec33cdf66939b653bf6800
Subproject commit a8db7dfe823def043368857b8fbfbba86f2e9e47

1
3rdparty/chromeec vendored Submodule

@ -0,0 +1 @@
Subproject commit e486b388a73f1e19f3142774d0b3ee166e8f41ff

2
3rdparty/cmocka vendored

@ -1 +1 @@
Subproject commit 8be37372097d1aa5e03b565936db7891b6180e73
Subproject commit 8931845c35e78b5123d73430b071affd537d5935

2
3rdparty/fsp vendored

@ -1 +1 @@
Subproject commit 81399b3b61479abc379c2d01362d4b6dc6f515c9
Subproject commit 481ea7cf0bae0107c3e14aa746e52657647142f3

@ -1 +1 @@
Subproject commit 250941fb670645d7d91f761cc63656ad3a1ec367
Subproject commit 6788bb07eb5f9e9b83c31ea1364150fe898f450a

2
3rdparty/libgfxinit vendored

@ -1 +1 @@
Subproject commit 3c3828add50024e90e57d6fbe0e660d1b66302d9
Subproject commit a4be8a21b0e2c752da0042c79aae5942418f53e2

@ -1 +0,0 @@
Subproject commit 591c8f53482243626901e1cc8a4ae321f314040d

2
3rdparty/qc_blobs vendored

@ -1 +1 @@
Subproject commit 6379308814bd00a8b6e36a4715bdb86ba019a3a7
Subproject commit a252198ec6544e13904cfe831cec3e784aaa715d

2
3rdparty/vboot vendored

@ -1 +1 @@
Subproject commit 5c360ef458b0a013d8a6d47724bb0fffb5accbcf
Subproject commit 24cb127a5e83a713131ab75cc39b11336019443c

137
AUTHORS
View file

@ -15,14 +15,12 @@ Aaron Durbin
Abe Levkoy
Abel Briggs
Abhinav Hardikar
Abhishek Pandit-Subedi
AdaCore
Adam Liu
Adam Mills
Advanced Computing Lab, LANL
Advanced Micro Devices, Inc.
AG Electronics Ltd.
Agogo
Ahamed Husni
Akshu Agrawal
Al Hirani
@ -41,42 +39,32 @@ Alexandru Gagniuc
Alexey Buyanov
Alexey Vazhnov
Alice Sell
Alicja Michalska
Allen-KH Cheng
Alok Agarwal
Alper Nebi Yasak
Amanda Hwang
American Megatrends International, LLC
Amersel
Amit Caleechurn
Ana Carolina Cabral
Analog Devices Inc.
Analogix Semiconductor
Anand Mistry
Anand Vaikar
Anastasios Koutian
Andre
Andre Heider
Andrew McRae
Andrew SH Cheng
Andrey Pronin
Andriy Gapon
Andy
Andy Fleming
Andy Pont
Andy-ld Lu
Angel Pons
Angela Czubak
Anil Kumar K
Anna Karaś
Annie Chen
Anton Kochkov
Ao Zhong
Appukuttan V K
Arashk Mahshidfar
Arec Kao
Ariel Fang
Ariel Otilibili
ARM Limited and Contributors
Arthur Heymans
Asami Doi
@ -86,12 +74,9 @@ Ashqti
ASPEED Technology Inc.
Atheros Corporation
Atmel Corporation
Avi Uday
Avinash Munduru
Balaji Manigandan
Balázs Vinarz
BAP - Bruhnspace Advanced Projects
Bartłomiej Grzesik
Baruch Siach
Ben Chuang
Ben Kao
@ -102,26 +87,20 @@ Bernardo Perez Priego
Bhanu Prakash Maiya
Bill Xie
Bin Meng
Bincai Liu
Bitland Tech Inc.
Bob Moragues
Bora Guvendik
Boris Barbulovski
Boris Mittelberg
Brandon Breitenstein
Brandon Weeks
Brian Hsu
Brian Norris
Bryant Ou
Carl-Daniel Hailfinger
Carlos López
Casper Chang
Cathy Xu
Caveh Jalali
Cavium Inc.
Chao Gui
Chen-Tsung Hsieh
Chen. Gang C
Chia-Ling Hou
Chien-Chih Tseng
Chris Wang
@ -141,7 +120,6 @@ Cong Yang
CoolStar
coresystems GmbH
Corey Osgood
Crystal Guo
Curt Brune
Curtis Chen
Custom Ideas
@ -150,7 +128,6 @@ Da Lao
Daisuke Nojiri
Damien Zammit
Dan Callaghan
Dan Campbell
Daniel Campello
Daniel Gröber
Daniel Kang
@ -161,7 +138,6 @@ Dave Airlie
David Brownell
David Greenman
David Hendricks
David Li
David Lin
David Milosevic
David Mosberger-Tang
@ -171,7 +147,6 @@ David Wu
Dawei Chien
Deepika Punyamurtula
Deepti Deshatty
Dehui Sun
Denis 'GNUtoo' Carikli
Denis Dowling
DENX Software Engineering
@ -185,7 +160,6 @@ Divya S Sasidharan
Dmitry Ponamorev
Dmitry Torokhov
DMP Electronics Inc.
Dolan Liu
Dominik Behr
Donghwa Lee
Drew Eckhardt
@ -206,10 +180,7 @@ ELSOFT AG
Eltan B.V
Eltan B.V.
Elyes Haouas
Emilie Roberts
Enzo Potenza
Eran Mitrani
Eren Peng
Eric Biederman
Eric Lai
Eric Peers
@ -221,21 +192,15 @@ Ethan Tsao
Eugene Myers
Evan Green
Evgeny Zinoviev
Evie (Ivi) Ballou
Fabian Groffen
Fabian Kunkel
Fabian Meyer
Fabio Aiuto
Fabrice Bellard
Facebook, Inc.
Federico Amedeo Izzo
Fei Yan
Felix Friedlander
Felix Held
Felix Singer
Fengquan Chen
Filip Brozovic
Filip Lewiński
Flora Fu
Florian Laufenböck
Francois Toguo Fotso
@ -249,13 +214,9 @@ Free Software Foundation, Inc.
Freescale Semiconductor, Inc.
Furquan Shaikh
Gaggery Tsai
Gang C Chen
Garen Wu
Gareth Yu
Gang C Chen
Garmin Chang
Gary Jennejohn
Gavin Liu
George Burgess
George Trudeau
Gerald Van Baren
Gerd Hoffmann
@ -263,7 +224,6 @@ Gergely Kiss
Google LLC
Greg Watson
Grzegorz Bernacki
Guangjie Song
Guennadi Liakhovetski
Guodong Liu
Gwendal Grignou
@ -271,21 +231,17 @@ Hal Martin
Hao Chou
Hao Wang
HardenedLinux
Harrie Paijmans
Harsha B R
Harshit Sharma
Henry C Chen
Herbert Wu
Hewlett Packard Enterprise Development LP
Hewlett-Packard Development Company, L.P.
Himanshu Sahdev
Hope Wang
Housong Zhang
Hsiao Chien Sung
Hsin-hsiung wang
Hsin-Te Yuan
Hsuan Ting Chen
Hualin Wei
Huaqin Technology Co., Ltd
Huaqin Telecom Inc.
Hui Liu
@ -300,7 +256,6 @@ Igor Pavlov
Ikjoon Jang
Imagination Technologies
Infineon Technologies
Ingo Reitz
InKi Dae
INSPUR Co., Ltd
Intel Corporation
@ -318,14 +273,11 @@ Jakub Czapiga
James Chao
James Lo
James Ye
Jameson Thies
Jamie Chen
Jamie Ryu
Jan Dabros
Jan Philipp Groß
Jan Samek
Jan Tatje
Jarried Lin
Jason Glenesk
Jason Nein
Jason V Le
@ -334,9 +286,6 @@ Jason Zhao
jason-ch chen
Jason-jh Lin
Jay Patel
Jayvik Desai
Jean Lucas
Jędrzej Ciupis
Jeff Chase
Jeff Daly
Jeff Li
@ -357,12 +306,9 @@ Jingle Hsu
Jitao Shi
Joe Pillow
Joe Tessler
Joel Bueno
Joel Kitching
Joel Linn
Joey Peng
Johanna Schander
Johannes Hahn
John Su
John Zhao
Johnny Li
@ -379,10 +325,7 @@ Jordan Crouse
Jörg Mische
Joseph Smith
Josie Nordrum
Juan José García-Castro Crespo
Julia Kittlinger
Julia Tsai
Julian Intronati
Julian Schroeder
Julian Stecklina
Julien Viard de Galbert
@ -391,12 +334,9 @@ Kacper Stojek
Kaiyen Chang
Kane Chen
Kangheui Won
KangMin Wang
Kapil Porwal
Karol Zmyslowski
Karthik Ramasubramanian
Ke Zheng
Kei Hiroyoshi
Keith Hui
Keith Packard
Kenneth Chan
@ -407,12 +347,10 @@ Kevin Chowski
Kevin Cody-Little
Kevin Keijzer
Kevin O'Connor
Kevin Yang
Kevin3 Yang
kewei xu
Kilari Raasi
Kirk Wang
Kiwi Liu
Konrad Adamczyk
Kontron Europe GmbH
Kornel Dulęba
@ -422,7 +360,6 @@ Kshitij
Kshitiz Godara
Kulkarni. Srinivas
Kun Liu
KunYi Chen
Kyle Lin
Kyösti Mälkki
Lance Zhao
@ -430,11 +367,9 @@ Lawrence Chang
Leah Rowe
Lean Sheng Tan
Lei Wen
Lennart Eichhorn
Lenovo Group Ltd
Leo Chou
Li-Ta Lo
Li1 Feng
Liam Flaherty
Libra Li
Libretrend LDA
@ -445,15 +380,10 @@ linear
Linus Torvalds
Linux Networx, Inc.
LiPPERT ADLINK Technology GmbH
Liu Liu
Liya Li
Lu Tang
Lu. Pen-ChunX
Lubomir Rintel
Luc Verhaegen
Luca Lai
Lucas Chen
Lukas Wunner
Mac Chiang
Maciej Matuszczyk
Maciej Pijanowski
@ -467,13 +397,11 @@ Marc Bertens
Marc Jones
Marco Chen
Marek Kasiewicz
Marek Maślanka
Marek Vasut
Mario Scheithauer
Marius Gröger
Mariusz Szafranski
Mariusz Szafrański
Mark Chang
Mark Hasemeyer
Mark Hsieh
Mars Chen
@ -484,7 +412,6 @@ Martin Roth
Marvell International Ltd.
Marvell Semiconductor Inc.
Marx Wang
Masa Nakura
Masanori Ogino
Máté Kukri
Matei Dibu
@ -493,7 +420,6 @@ Matt Chen
Matt Delco
Matt DeVillier
Matt Papageorge
Matt Turner
Matthew Blecker
Matthew Ziegelbaum
Mattias Nissler
@ -506,7 +432,6 @@ Maximilian Brune
Mediatek Inc.
MediaTek Inc.
Meera Ravindranath
Melongmelong
Meng-Huan Yu
Meta Platforms, Inc
mgabryelski1
@ -519,20 +444,15 @@ Michael Strosche
Michael Walle
Michał Kopeć
Michal Suchanek
Michał Zieliński
Michał Żygowski
Micro-Star INT'L CO., LTD.
Mika Westerberg
Mike Banon
Mike Lin
Mike Shih
Mingjin Ge
Miriam Polzer
mkurumel
Moises Garcia
Momoko Hattori
Mondrian Nuessle
Monika A
Monikaanan
MontaVista Software, Inc.
Morgan Jang
@ -542,25 +462,21 @@ mtk15698
mturney mturney
Musse Abdullahi
Myles Watson
Nancy Lin
Nancy.Lin
Naresh Solanki
Nathan Lu
Naveen R. Iyer
Neill Corlett
Network Appliance Inc.
Nicholas Chin
Nicholas Sielicki
Nicholas Sudsgaard
Nick Barker
Nick Chen
Nick Kochlowski
Nick Vaccaro
Nico Huber
Nico Rikken
Nicola Corna
Nicolas Boichat
Nicole Faerber
Nigel Tao
Nikolai Vyssotski
Nils Jacobs
Nina Wu
@ -574,10 +490,6 @@ Omar Pakker
Online SAS
Opal Voravootivat
Orion Technologies, LLC
Ot_chhao.chang
Ot_hao.han
Ot_song Fan
Pablo
Pablo Ceballos
Pablo Stebler
Pan Gao
@ -590,7 +502,6 @@ Paul Fagerburg
Paul Menzel
Paul2 Huang
Paulo Alcantara
Pavan Holla
Pavel Sayekat
Paz Zcharya
PC Engines GmbH
@ -607,22 +518,17 @@ Philipp Bartsch
Philipp Degler
Philipp Deppenwiese
Philipp Hug
Pierce Chou
Piotr Kleinschmidt
Po Xu
Poornima Tom
Pranava Y N
Prasad Malisetty
Prashant Malani
Pratik Vishwakarma
Pratikkumar Prajapati
Pratikkumar V Prajapati
Protectli
PugzAreCute
Purdea Andrei
Purism SPC
Purism, SPC
Qii Wang
Qinghong Zeng
Qualcomm Technologies, Inc.
Quanta Computer INC
Raihow Shi
@ -637,7 +543,6 @@ Ravindra
Ravishankar Sarawadi
Ray Han Lim Ng
Raymond Chung
Reagan
Red Hat, Inc
ReddestDream
Rehan Ghori
@ -655,7 +560,6 @@ Richard Woodruff
Rick Lee
Ricky Chang
Riku Viitanen
Rishika Raj
Ritul Guru
Rizwan Qureshi
Rnhmjoj
@ -668,14 +572,12 @@ Robinson P. Tryon
Rockchip, Inc.
Rocky Phagura
Roger Lu
Roger Wang
Roja Rani Yarubandi
Romain Lievin
Roman Zippel
Ron Lee
Ron Minnich
Ronak Kanabar
Ronald Claveau
Ronald G. Minnich
Rory Liu
Rudolf Marek
@ -697,7 +599,6 @@ Samuel Holland
Sandeep Maheswaram
Sathya Prakash M R
Satya Priya Kakitapalli
Satya SreenivasL
Saurabh Mishra
SciTech Software, Inc.
Scott Chao
@ -725,7 +626,6 @@ Shiyu Sun
Shon Wang
Shou-Chieh Hsu
Shreesh Chhabbi
Shunxi Zhang
Shuo Liu
Siemens AG
SiFive, Inc
@ -738,12 +638,10 @@ Simon Zhou
Sindhoor Tilak
Solomon Alan-Dei
Song Fan
Sowmya Aralguppe
Sridhar Siricilla
Srinidhi N Kaushik
Srinivasa Rao Mandadapu
ST Microelectronics
Stanisław Kardach
Stanley Wu
Star Labs Online Ltd
Stefan Binding
@ -771,7 +669,6 @@ Tao Xia
Tarun Tuli
Teddy Shih
Terry Chen
Terry Cheong
Texas Instruments
The Android Open Source Project
The ChromiumOS Authors
@ -790,9 +687,7 @@ Timothy Pearson
tinghan shen
Tobias Diedrich
Tom Hiller
Tomasz Michalec
Tommie Lin
Tongtong Pan
Tony Huang
Tracy Wu
Trevor Wu
@ -809,13 +704,10 @@ Usha P
Uwe Hermann
Uwe Poeche
V Sowmya
Vladimir Epifantsev
Václav Straka
Vadim Bendebury
Valentyn Sudomyr
Van Chen
Varshit B Pandya
Varun Upadhyay
Veerabhadrarao Badiganti
Venkat Thogaru
Venkata Krishna Nimmagadda
@ -824,7 +716,6 @@ Victor Ding
Vidya Gopalakrishnan
Vikram Narayanan
Vikrant L Jadeja
Vince Liu
Vinod Polimera
Vipin Kumar
Vitaly Rodionov
@ -837,10 +728,8 @@ Ward Vandewege
Wayne Wang
Weimin Wu
Weiyi Lu
Wen Zhang
Wenbin Mei
Wentao Qin
Wenzhen Yu
Werner Zeh
Wilbert Duijvenvoorde
William Wei
@ -856,19 +745,13 @@ Wojciech Macek
Wolfgang Denk
Won Chung
Wonkyu Kim
Wuxy
Xiang W
Wuxy
Xin Ji
Xiwen Shao
Xixi Chen
Xue Yao
Xueqi Zhang
Xuxin Xiong
YADRO
Yan Liu
Yang Wu
Yann Collet
Yanqiong Huang
Yaroslav Kurlaev
YH Lin
Yidi Lin
@ -883,28 +766,20 @@ Yu-Ping Wu
Yuanliding
Yuchen He
Yuchen Huang
Yuchiche
Yunlong Jia
Yuval Peress
Zachary Yedidia
Zanxi Chen
Zebreus
Zhanyong Wang
Zhaoming Luo
Zhaoqing Jiu
Zheng Bao
Zhenguo Li
Zhi7 Li
Zhigang Qin
Zhiqiang Ma
Zhixing Ma
Zhiyong Tao
Zhongtian Wu
zhongtian wu
Zhuohao Lee
Ziang Wang
Zoey Wu
Zoltan Baldaszti
一颗小土豆
小田喜陽彦
忧郁沙茶
陳建宏
陳建宏

View file

@ -5,7 +5,7 @@
#
BUILDDIR ?= _build
SPHINXOPTS ?= -j auto -W --keep-going
SPHINXOPTS ?= -j auto
export SPHINXOPTS
@ -31,7 +31,8 @@ livesphinx: $(BUILDDIR)
test:
@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:
@echo "all - Builds all documentation targets"

View file

@ -1,29 +1,234 @@
## 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
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SPHINXAUTOBUILD = sphinx-autobuild
SOURCEDIR = .
BUILDDIR = _build
# You can set these variables from the command line.
SPHINXOPTS ?=
SPHINXBUILD = sphinx-build
SPHINXAUTOBUILD = sphinx-autobuild
PAPER =
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:
@$(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
livehtml:
@echo "Starting sphinx-autobuild. The HTML pages are in $(BUILDDIR)."
@echo "Press Ctrl-C to stop."
@echo
$(SPHINXAUTOBUILD) "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
$(SPHINXAUTOBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile.sphinx
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: dirhtml
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@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."

View file

@ -5,7 +5,7 @@ coreboot POST Codes
This is an (incomplete) list of POST codes emitted by coreboot v4.
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
0x12 Copy/decompression finished jumping to RAM
0x80 Entry into coreboot in RAM

View file

@ -1,7 +1,3 @@
```{eval-rst}
:orphan:
```
# Background
CB:31250 ("soc/intel/cannonlake: Configure GPIOs again after FSP-S is

View file

@ -5,27 +5,15 @@ backwards support for ACPI 1.0 and is only compatible to ACPI version 2.0 and
upwards.
```{toctree}
:maxdepth: 1
SSDT UID generation <uid.md>
```
- [SSDT UID generation](uid.md)
## GPIO
```{toctree}
:maxdepth: 1
GPIO toggling in ACPI AML <gpio.md>
```
- [GPIO toggling in ACPI AML](gpio.md)
## Windows-specific ACPI documentation
```{toctree}
:maxdepth: 1
Windows-specific documentation <windows.md>
```
- [Windows-specific documentation](windows.md)
## ACPI specification - Useful links

View file

@ -18,7 +18,6 @@ Spec](https://uefi.org/specifications) for details, or run the tool
initialization that happens from the PSP. Significantly, Memory
Initialization.
* AC - Electricity: [**Alternating Current**](https://en.wikipedia.org/wiki/Alternating_current)
* ACE - AXI Coherency Extensions
* Ack - Acknowledgment / Acknowledged
* ACM [**Authenticated Code Module**](https://doc.coreboot.org/security/intel/acm.html)
* 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)
* ANSI - [**American National Standards Institute**](https://en.wikipedia.org/wiki/American_National_Standards_Institute)
* 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
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
Strap Processor).
* APB - Advanced Peripheral Bus (part of the AMBA bus specification)
* 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)
* APIC - [**Advanced Programmable Interrupt
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)
* ATX - [**Advanced Technology eXtended**](https://en.wikipedia.org/wiki/ATX)
* 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
@ -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)
* 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)
* CHI - Coherent Hub Interface
* CID - [**Coverity ID**](https://en.wikipedia.org/wiki/Coverity)
* CIM - [**Common Information Model**](https://www.dmtf.org/standards/cim)
* 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
(End-of-Line) marker.
* 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)
* CSE - Intel: Converged Security Engine
* 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)
* GPE - ACPI: General Purpose Event
* 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
* GPO - GPIOs: GPIO Output
* 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
mainboard.
* ISP - Internet Service Provider
* ISP - Image-Signal-Process
* IVHD - ACPI: I/O Virtualization Hardware Definition
* IVMD - ACPI: I/O Virtualization Memory Definition
* 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
* STAPM - AMD: Skin Temperature Aware Power Management
* 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)
(SIO) device provides a system with any of a number of different
peripherals. Most common are: A PS/2 Keyboard and mouse port, LPT

View file

@ -5,15 +5,7 @@ architectures.
## RISC-V
```{toctree}
:maxdepth: 1
RISC-V documentation <riscv/index.md>
```
- [RISC-V documentation](riscv/index.md)
## x86
```{toctree}
:maxdepth: 1
x86 documentation <x86/index.md>
```
- [x86 documentation](x86/index.md)

View file

@ -2,9 +2,94 @@
This section contains documentation about coreboot on x86 architecture.
```{toctree}
:maxdepth: 1
* [x86 PAE support](pae.md)
x86 PAE support <pae.md>
x86_64 support <x86_64.md>
```
## State of x86_64 support
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.

View file

@ -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.

View file

@ -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
(and without refund in the case of a paid event).
As a part of running the project, coreboot leadership has the right to
revoke privileges as they see fit. This is not done lightly. Over the
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.
Community organizers can be members of the arbitration team, or organizers
of events and online communities.
## 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
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
Threatening or starting legal action against the project, sibling
@ -125,18 +115,12 @@ communications pertaining to community business.
## Contact info
Our arbitration team currently consists of the following people
* Daniel Pono Takamori <pono@sfconservancy.org> (USA)
Our arbitration team consists of the following people
* Stefan Reinauer <stefan.reinauer@coreboot.org> (USA)
* Patrick Georgi <patrick@coreboot.org> (Germany)
* Ronald Minnich <rminnich@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
This Code of Conduct is distributed under

View file

@ -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 its 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.

View file

@ -1,11 +1,6 @@
# Community
```{toctree}
:maxdepth: 1
Code of Conduct <code_of_conduct.md>
Language style <language_style.md>
Community forums <forums.md>
coreboot at conferences <conferences.md>
Cross-Project Collaboration <cross_project_collaboration.md>
```
* [Code of Conduct](code_of_conduct.md)
* [Language style](language_style.md)
* [Community forums](forums.md)
* [coreboot at conferences](conferences.md)

View file

@ -1,35 +1,54 @@
# Configuration file for the Sphinx documentation builder.
#
# 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
# -*- coding: utf-8 -*-
import subprocess
from recommonmark.parser import CommonMarkParser
import sphinx
project = 'coreboot'
copyright = 'CC-by 4.0 the coreboot project'
author = 'the coreboot project'
# Get Sphinx version
major = 0
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")
# The short X.Y version.
version = release.split("-")[0]
extensions = []
# Load recommonmark, supported since 1.8+
if major >= 2 or (major == 1 and minor >= 8):
extensions += ['recommonmark']
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
extensions = ["myst_parser"]
myst_heading_anchors = 5
myst_url_schemes = ["http", "https", "mailto", "ftp", "ircs"]
templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# Try to load DITAA
try:
import sphinxcontrib.ditaa
except ImportError:
print("Error: Please install sphinxcontrib.ditaa for ASCII art conversion\n")
else:
extensions += ['sphinxcontrib.ditaa']
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@ -38,11 +57,62 @@ pygments_style = 'sphinx'
# Usually you set "language" from the command line for these cases.
language = 'en'
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
# List of patterns, relative to source directory, that match files and
# 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'
# 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_css_files = [
'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)

View file

@ -522,7 +522,7 @@ The preferred style for *long* (multi-line) comments is:
```c
/*
 * This is the preferred style for long multi-line
 * This is the preferred style for multi-line
 * comments in the coreboot source code.
 * Please use it consistently.
 *
@ -808,7 +808,7 @@ eDP display panel encounters an I2C error, it should print a "cannot read EDID"
message and return an error code. The calling display initialization function
knows that without the EDID there is no way to initialize the display correctly,
so it will also immediately return with an error code without running its
remaining code that would initialize the SoC's display controller. Execution
remaining code that would initialize the SoC's display controller. Exeuction
returns further up the function stack to the mainboard initialization code
which continues booting despite the failed display initialization, since
display functionality is non-essential to the system. (Code is encouraged but

View file

@ -304,7 +304,7 @@ would be a good reviewer, look in the MAINTAINERS file or git history of
the files that youve changed, and add those people.
* 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
message to a minimum.
@ -348,8 +348,8 @@ commit message itself:
* Tested-by:
* Reviewed-by:
The script `util/scripts/cross-repo-cherrypick` can be used to help
automate this. Other tags such as 'Commit-Queue' can simply be removed.
The script `util/gitconfig/rebase.sh` can be used to help automate this.
Other tags such as 'Commit-Queue' can simply be removed.
* 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
@ -395,8 +395,8 @@ Gerrit user roles
There are a few relevant roles a user can have on Gerrit:
- The anonymous user can check out source code.
- A registered user can also comment and give "+1" code reviews.
- A reviewer can give "-1" and "+2" code reviews.
- A registered user can also comment and give "+1" and "-1" code reviews.
- A reviewer can also give "+2" code reviews.
- A core developer can also give "-2" (that is, blocking) code reviews
and submit changes.
@ -433,55 +433,8 @@ reversed after they come back.
Requests for clarification and suggestions for updates to these guidelines
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
[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/
[this LKML thread]: https://lkml.org/lkml/2004/5/23/10
[SCO-Linux disputes]: https://en.wikipedia.org/wiki/SCO%E2%80%93Linux_disputes
[coreboot's bug tracker]: https://ticket.coreboot.org/

View file

@ -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.

View file

@ -1,29 +1,7 @@
# Contributing
```{toctree}
:maxdepth: 1
Coding Style <coding_style.md>
Gerrit Guidelines <gerrit_guidelines.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
* [Coding Style](coding_style.md)
* [Gerrit Guidelines](gerrit_guidelines.md)
* [Project Ideas](project_ideas.md)
* [Documentation Ideas](documentation_ideas.md)
* [Google Summer of Code](gsoc.md)

View file

@ -29,7 +29,7 @@ sealings are sent via encrypted email.
### 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
[3mdeb](https://3mdeb.com/). NovaCustom offers full GNU/Linux and Microsoft
Windows compatibility. NovaCustom ensures security updates via fwupd for 5 years
@ -43,16 +43,6 @@ ships with coreboot and support upstream maintenance for the devices through a
third party, [3mdeb](https://3mdeb.com). They provide current and tested
firmware binaries on [GitHub](https://pcengines.github.io).
### Protectli
[Protectli](https://protectli.com) is dedicated to providing reliable,
cost-effective, and secure computer equipment with coreboot-based firmware
tailored for their hardware. It comes with the [Dasharo](#dasharo)
firmware, maintained by [3mdeb](https://3mdeb.com/). Protectli hardware has
verified support for many popular operating systems, such as Linux distributions,
FreeBSD, and Windows. Support includes Debian, Ubuntu, OPNsense, pfSense,
ProxMox VE, VMware ESXi, Windows 10 and 11, and many more.
### Purism
[Purism](https://www.puri.sm) sells laptops with a focus on user privacy and

View file

@ -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)

View file

@ -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"
```

View file

@ -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
},
};
```

View file

@ -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.

View file

@ -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).
```{toctree}
:maxdepth: 1
:hidden:
Driver Devicetree Entries <dt_entries.md>
```
Some of the drivers currently available include:
```{toctree}
:maxdepth: 1
ACPI Five-Level Fan Control <acpi_fan_control.md>
CFR <cfr.md>
CFR use within coreboot <cfr_internal.md>
Intel DPTF <dptf.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>
```
* [Intel DPTF](dptf.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)

View file

@ -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

View file

@ -128,8 +128,7 @@ data or modify the currently running kernel.*
## 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.
[SMM]: ../security/smm.md

View file

@ -74,30 +74,19 @@ has to read the coreboot table with tag `0x0039`, containing:
struct lb_smmstorev2 {
uint32_t tag;
uint32_t size;
uint32_t num_blocks; /* Number of writable blocks in SMM */
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.
Prefer 'mmap_addr' for new software.
Zero when the address won't fit into 32-bits. */
uint32_t com_buffer; /* Physical address of the communication buffer */
uint32_t com_buffer_size; /* Size of the communication buffer in bytes */
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. */
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 mmap_addr; /* MMIO address of the store for read only access */
uint32_t com_buffer; /* Physical address of the communication buffer */
uint32_t com_buffer_size; /* Size of the communication buffer in byte */
uint8_t apm_cmd; /* The command byte to write to the APM I/O port */
uint8_t unused[3]; /* Set to zero */
};
```
The absence of this coreboot table entry indicates that there's no
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
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
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
@ -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
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
* [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.
[SMM]: ../security/smm.md

View file

@ -41,7 +41,7 @@ The bootblock loads the romstage or the verstage if verified boot is enabled.
### Cache-As-Ram
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.
The CAR needs to be activated using vendor specific CPU instructions.

View file

@ -7,10 +7,10 @@ to the point of providing its own custom language.
The overhead of learning this new syntax is (hopefully) offset by its lower
complexity.
The build system is defined in the toplevel `Makefile` and `toolchain.mk`
The build system is defined in the toplevel `Makefile` and `toolchain.inc`
and is supposed to be generic (and is in fact used with a number of other
projects). Project specific configuration should reside in files called
`Makefile.mk`.
`Makefile.inc`.
In general, the build system provides a number of "classes" that describe
various parts of the build. These cover the various build targets in coreboot
@ -36,7 +36,7 @@ TODO: explain how to create new classes and how to evaluate them.
### subdirs
`subdirs` contains subdirectories (relative to the current directory) that
should also be handled by the build system. The build system expects these
directories to contain a file called `Makefile.mk`.
directories to contain a file called `Makefile.inc`.
Subdirectories are not read at the point where the `subdirs` statement
resides but later, after the current directory is handled (and potentially
@ -66,7 +66,7 @@ supported options are:
You can use the `add_intermediate` helper to add new post-processing steps for
the final `coreboot.rom` image. For example you can add new files to CBFS by
adding something like this to `site-local/Makefile.mk`
adding something like this to `site-local/Makefile.inc`
```
$(call add_intermediate, add_mrc_data)
@ -75,7 +75,9 @@ $(call add_intermediate, add_mrc_data)
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
With the addition of FMAP flash partitioning support to coreboot, there was a
@ -98,4 +100,4 @@ The default implementation just returns `COREBOOT` (the default region) for
all files.
vboot provides its own implementation of `regions-for-file` that can be used
as reference in `src/vboot/Makefile.mk`.
as reference in `src/vboot/Makefile.inc`.

View file

@ -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.

View file

@ -1,312 +0,0 @@
# coreboot FAQ
## General coreboot questions
### What is coreboot?
coreboot is a free and open software project designed to initialize
computers and embedded systems in a fast, secure, and auditable fashion.
The focus is on minimal hardware initialization: to do only what is
absolutely needed, then pass control to other software (a payload, in
coreboot parlance) in order to boot the operating system securely.
### What is a coreboot payload?
coreboot itself does not deal with boot media such as hard-drives,
SSDs, or USB flash-drives, beyond initializing the underlying hardware.
So in order to actually boot an operating system, another piece of
software which does do those things must be used. coreboot supports
a large number of diverse payloads; see below for more details.
### Is coreboot the same as UEFI?
No. coreboot and UEFI are both system firmware that handle the
initialization of the hardware, but are otherwise not similar.
coreboots goal is to **just** initialize the hardware and exit.
This makes coreboot smaller and simpler, leading to faster boot times,
and making it easier to find and fix bugs. The result is a higher
overall security.
### What's the difference between coreboot and UEFI?
UEFI is actually a firmware specification, not a specific software
implementation. Intel, along with the rest of the Tianocore project,
has released an open-source implementation of the overall framework,
EDK2, but it does not come with hardware support. Most hardware running
UEFI uses a proprietary implementation built on top of EDK2.
coreboot does not implement the UEFI specification, but it can be used to
initialize the system, then launch a UEFI payload such as EDK2 in order
to provide UEFI boot services.
The UEFI specification also defines and allows for many things that are
outside of coreboots scope, including (but not limited to):
* Boot device selection
* Updating the firmware
* A CLI shell
* Network communication
* An integrated setup menu
### Can coreboot boot operating systems that require UEFI?
Yes, but... again, coreboot **just** initializes the hardware. coreboot
itself doesnt load operating systems from storage media other than the
flash chip. Unlike UEFI, coreboot does not, and will not contain a Wi-Fi
driver or communicate directly with any sort of network. That sort of
functionality is not related to hardware initialization.
To boot operating systems that require UEFI, coreboot can be compiled with
EDK2 as the payload. This allows coreboot to perform the hardware init,
with EDK2 supplying the UEFI boot interface and runtime services to
the operating system.
### What non-UEFI payloads does coreboot support?
* SeaBIOS, behaves like a classic BIOS, allowing you to boot operating
systems that rely on the legacy interrupts.
* GRUB can be used as a coreboot payload, and is currently the most
common approach to full disk encryption (FDE).
* A Linux kernel and initramfs stored alongside coreboot in the boot
ROM can also be used as a payload. In this scenario coreboot
initializes hardware, loads Linux from boot ROM into RAM, and
executes it. The embedded Linux environment can look for a target OS
kernel to load from local storage or over a network and execute it
using kexec. This is sometimes called LinuxBoot.
* U-boot, depthcharge, FILO, etc.
Theres [https://doc.coreboot.org/payloads.html](https://doc.coreboot.org/payloads.html)
with a list, although its not complete.
### What does coreboot leave in memory after it's done initializing the hardware?
While coreboot tries to remove itself completely from memory after
finishing, some tables and data need to remain for the OS. coreboot
reserves an area in memory known as CBMEM, to save this data after it
has finished booting. This contains things such as the boot log, tables
that get passed to the payload, SMBIOS, and ACPI tables for the OS.
In addition to CBMEM, on X86 systems, coreboot will typically set up
SMM, which will remain resident after coreboot exits.
## Platforms
### Whats the best coreboot platform for a user?
The choice of the best coreboot platform for a user can vary depending
on their specific needs, preferences, and use cases.
Typically, people who want a system with a minimum of proprietary
firmware are restricted to older systems like the Lenovo X220, or more
expensive, non-x86 solutions like TALOS, from Raptor Engineering.
There are a number of companies selling modern systems, but those all
require more proprietary binaries in addition to coreboot (e.g., Intel
FSP). However, unlike the older ThinkPads, many of these newer devices
use open-source embedded controller (EC) firmware, so there are
tradeoffs with either option.
The coreboot project mantains a list of companies selling machines
which use coreboot on the [website](https://coreboot.org/users.html).
### Whats the best platform for coreboot development?
Similar to the best platform for users, the best platform for
developers very much depends on what a developer is trying to do.
* QEMU is generally the easiest platform for coreboot development, just
because its easy to run anywhere. However, its possible for things
to work properly in QEMU but fail miserably on actual hardware.
While laptops tend to be harder to develop than desktop platforms, a
majority of newer platforms on coreboot tend to be laptops. The
development difficulty is due to a few different factors:
1. The EC (Embedded Controller) is a specialized microcontroller that
typically handles keyboard and sometimes mouse input for a laptop.
It also controls many power management functions such as fans, USB-C
power delivery, etc. ECs run mainboard-specific firmware, which is
typically undocumented.
2. ThinkPads (X230, 30-series, 20-series, T430, T540, T520). Sandy
Bridge and Ivy Bridge are well-supported. Some may have
difficult-to-reach SPI flash chips. Boards with two flash chips (e.g.
30-series ThinkPads) are harder to externally reflash as one needs to
make sure the non-targeted flash chip remains disabled at all times.
The X230 is notoriously sensitive to external reflashing issues.
3. Laptops often lack a convenient method to obtain firmware boot logs.
One can use EHCI debug on older systems and Chromebook-specific
solutions for Chromebooks, but one often has to resort to flashconsole
(writing coreboot logs to the flash chip where coreboot resides). On
the other hand, several desktop mainboards still have a RS-232 serial
port.
Some of the easiest physical systems to use for coreboot development
are Chromebooks. Newer Chromebooks allow for debug without opening the
case. Look for SuzyQ Cables or SuzyQables or instructions on how to
build one. These cables only work on a specific port in a specific
orientation. Google [supplies
specifications](https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/master/docs/ccd.md#SuzyQ-SuzyQable)
for these cables.
### What platforms does coreboot support?
The most accurate way to determine what systems coreboot supports is by
browsing the src/mainboard tree or running “make menuconfig” and going
through the “Mainboard” submenu. You can also search Gerrit to see if
there are any unmerged ports for your board.
There is also the board status page
([https://coreboot.org/status/board-status.html](https://coreboot.org/status/board-status.html)),
however this does not currently show supported board variants.
## coreboot Development
### Can coreboot be ported to [this board]?
The best way to determine if coreboot can be ported to a system is to
see if the processor and chipset is supported. The next step is to see
whether the system is locked to the proprietary firmware which comes
with the board.
Intel Platforms:
* coreboot only supports a few northbridges (back when northbridges
were on a separate package), and there's next to no support for
"server" platforms (multi-socket and similar things). Here's a list
of more recent supported Intel processors:
* Alder Lake (2021 - Core Gen 12)
* Apollo Lake (2016 - Atom)
* Baytrail (2014 - Atom)
* Braswell (2016 - Atom)
* Broadwell (2014 - Core Gen 5)
* Comet Lake (2019 - Core Gen 10)
* Cannon Lake (2018 - Core Gen 8/9)
* Denverton (2017)
* Elkhart lake (2021 - Atom)
* Haswell (2013 - Core Gen 4)
* Ivy Bridge (2012 - Core Gen 3)
* Jasper Lake (2021 - Atom)
* Kaby Lake (2016 - Core Gen 7/8)
* Meteor Lake (2023 - Gen 1 Ultra-mobile)
* Sandy Bridge (2011 - Core Gen 2)
* Sky Lake (2015 - Core Gen 6)
* Tiger Lake (2020 - Core Gen 11)
* Whiskey Lake (2018 - Core Gen 8)
* Intel Boot Guard is a security feature which tries to prevent loading
unauthorized firmware by the mainboard. If supported by the platform,
and the platform is supported by intelmetool, you should check if Boot
Guard is enabled. If it is, then getting coreboot to run will be
difficult or impossible even if it is ported. You can run
`intelmetool -b` on supported platforms to see if Boot Guard is
enabled (although it can fail because it wants to probe the ME
beforehand).
AMD Ryzen-based platforms:
* The AMD platforms Ryzen-based platforms unfortunately are currently
not well supported outside of the Chromebooks (and AMD reference
boards) currently in the tree.
The responsible teams are trying to fix this, but currently it's
**very** difficult to do a new port. Recent supported SoCs:
* Stoney Ridge
* Picasso
* Cezanne
* Mendocino
* Phoenix
General notes:
* Check the output of `lspci` to determine what processor/chipset
family your system has. Processor/chipset support is the most
important to determine if a board can be ported.
* Check the output of `superiotool` to see if it detects the Super I/O
on the system. You can also check board schematics and/or boardviews
if you can find them, or physically look at the mainboard for a chip
from one of the common superio vendors.
* Check what EC your system has (mostly applicable to laptops, but some
desktops have EC-like chips). You will likely need to refer to the
actual board or schematics/boardviews for this. Physical observation
is the most accurate identification procedure; software detection can
then be used to double-check if the chip is correct, but one should
not rely on software detection alone to identify an EC.
### How do I port coreboot to [this board]?
A critical piece for anyone attempting to do a board port is to make
sure that you have a method to recover your system from a failed flash.
We need an updated motherboard porting guide, but currently the guide
on the [wiki](https://www.coreboot.org/Motherboard_Porting_Guide) looks
to be the best reference.
At the moment, the best answer to this question is to ask for help on
one of the [various community
forums](https://doc.coreboot.org/community/forums.html).
### What about the Intel ME?
There seems to be a lot of FUD about what the ME can and cant do.
coreboot currently does not have a clear recommendation on how to
handle the ME. We understand that there are serious concerns about the
ME, and would like to flatly recommend removing as much as possible,
however modifying the ME can cause serious stability issues.
Additionally, coreboot and the Intel ME are completely separate entites
which in many cases simply happen to occupy the same flash chip. It is
not necessary to run coreboot to modify the ME, and running coreboot
does not imply anything about the ME's operational state.
#### A word of caution about the modifying ME
Messing with the ME firmware can cause issues, and this is outside the
scope of the coreboot project.
If you do decide to modify the ME firmware, please make sure coreboot
works **before** messing with it. Even if the vendor boot firmware
works when the ME isn't operating normally, it's possible that coreboot
doesn't handle it the same way and something breaks. If someone asks
for help with coreboot and we think the ME state may be a factor, we'll
ask them to try reproducing the issue with the ME running normally to
reduce the number of variables involved. This is especially important
when flashing coreboot for the first time, as it's best for newbies to
start with small steps: start by flashing coreboot to the BIOS region
and leaving the remaining regions untouched, then tinker around with
coreboot options (e.g. other payloads, bootsplash, RAM overclock...),
or try messing with the ME firmware **without changing coreboot**.
Most people don't understand the implications of messing with the ME
firmware, especially the use of `me_cleaner`. We admit that we don't
know everything about the ME, but we try to understand it as much as
possible. The ME is designed to operate correctly with the HAP (or
AltMeDisable) bit set, and it will gracefully enter a debug state (not
normal, but not an error). However, when using `me_cleaner` to remove
parts of the ME firmware, the ME will often end up in an error state
because parts of its FW are missing. It is known that removing some of
these parts ([`EFFS` and `FCRS` on Cougar Point,
c.f.](https://review.coreboot.org/c/coreboot/+/27798/6/src/mainboard/asus/p8h61-m_lx/Kconfig#63))
can cause problems. We do not know whether the state the ME ends up in
after applying `me_cleaner` is as secure as the state the ME goes to
when only the HAP bit is set: the removed FW modules could contain
steps to lock down important settings for security reasons.
To sum up, **we do not recommend messing with the ME firmware**. But if
you have to, please use `ifdtool` to set the HAP bit initially before
progressing to `me_cleaner` if necessary.

View file

@ -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
supports four different types of GPIO reset as:
```{eval-rst}
```eval_rst
+------------------------+----------------+-------------+-------------+
| | | PAD Reset ? |
+ PAD Reset Config + Platform Reset +-------------+-------------+

View file

@ -1,15 +1,9 @@
# Getting Started
```{toctree}
:maxdepth: 1
coreboot architecture <architecture.md>
Build System <build_system.md>
Submodules <submodules.md>
Kconfig <kconfig.md>
Writing Documentation <writing_documentation.md>
Setting up GPIOs <gpio.md>
Adding devices to a device tree <devicetree.md>
CBMEM <cbmem.md>
Frequently Asked Questions <faq.md>
```
* [coreboot architecture](architecture.md)
* [Build System](build_system.md)
* [Submodules](submodules.md)
* [Kconfig](kconfig.md)
* [Writing Documentation](writing_documentation.md)
* [Setting up GPIOs](gpio.md)
* [Adding devices to a device tree](devicetree.md)

View file

@ -69,6 +69,9 @@ These variables are typically set in the makefiles or on the make command line.
These variables were added to Kconfig specifically for coreboot and are not
included in the Linux version.
- KCONFIG_STRICT=value. Define to enable warnings as errors. This is enabled
in coreboot, and should not be changed.
- KCONFIG_NEGATIVES=value. Define to show negative values in the autoconf.h file
(build/config.h). This is enabled in coreboot, and should not be changed.
@ -99,9 +102,6 @@ included in the Linux version.
- KCONFIG_SPLITCONFIG=”directory name for individual SYMBOL.h files”.
coreboot sets this to $(obj)/config.
- KCONFIG_WERROR=value. Define to enable warnings as errors. This is enabled
in coreboot, and should not be changed.
#### Used only for make menuconfig
- MENUCONFIG_MODE=single_menu. Set to "single_menu" to enable. All other
values disable the option. This makes submenus appear below the menu option
@ -196,9 +196,9 @@ values to be set based on other values.
visible in the front end.
### Keywords
## Keywords
#### bool
### bool
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
@ -234,7 +234,7 @@ bool \[prompt\] \[if &lt;expr&gt;\]
--------------------------------------------------------------------------------
#### choice
### choice
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,
@ -297,7 +297,7 @@ choice \[symbol\]
--------------------------------------------------------------------------------
#### comment
### comment
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.
@ -322,7 +322,7 @@ comment &lt;prompt&gt;
--------------------------------------------------------------------------------
#### config
### config
This is the keyword that starts a block defining a Kconfig symbol. The symbol
modifiers follow the 'config' statement.
@ -359,7 +359,7 @@ config &lt;symbol&gt;
--------------------------------------------------------------------------------
#### default
### default
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
@ -399,7 +399,7 @@ default &lt;expr&gt; \[if &lt;expr&gt;\]
--------------------------------------------------------------------------------
#### def_bool
### def_bool
def_bool is similar to the 'bool' keyword in that it sets a symbols type to
boolean. It lets you set the type and default value at the same time, instead
@ -433,7 +433,7 @@ def_bool &lt;expr&gt; \[if &lt;expr&gt;\]
--------------------------------------------------------------------------------
#### depends on
### depends on
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
@ -462,28 +462,28 @@ depends on &lt;expr&gt;
--------------------------------------------------------------------------------
#### endchoice
### endchoice
This ends a choice block. See the 'choice' keyword for more information and an
example.
--------------------------------------------------------------------------------
#### endif
### endif
This ends a block started by the 'if' keyword. See the 'if' keyword for more
information and an example.
--------------------------------------------------------------------------------
#### endmenu
### endmenu
This ends a menu block. See the 'menu' keyword for more information and an
example.
--------------------------------------------------------------------------------
#### help
### help
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
@ -515,7 +515,7 @@ help &lt;help text&gt;
--------------------------------------------------------------------------------
#### hex
### hex
This is another symbol type specifier, specifying an unsigned integer value
formatted as hexadecimal.
@ -551,7 +551,7 @@ hex &lt;expr&gt; \[if &lt;expr&gt;\]
--------------------------------------------------------------------------------
#### if
### if
The 'if' keyword is overloaded, used in two different ways. The first definition
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
numeric values. The values can be further restricted with the range keyword.
@ -628,7 +628,7 @@ int &lt;expr&gt; \[if &lt;expr&gt;\]
--------------------------------------------------------------------------------
#### mainmenu
### mainmenu
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
@ -648,7 +648,7 @@ mainmenu "coreboot configuration"
--------------------------------------------------------------------------------
#### menu
### menu
The 'menu' and 'endmenu' keywords tell the configuration front end that the
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
configuration front end.
@ -748,7 +748,7 @@ prompt &lt;prompt&gt; \[if &lt;expr&gt;\]
prompt "Prompt value 2"
--------------------------------------------------------------------------------
#### range
### range
This sets the allowable minimum and maximum entries for hex or int type config
symbols.
@ -770,7 +770,7 @@ range &lt;symbol&gt; &lt;symbol&gt; \[if &lt;expr&gt;\]
--------------------------------------------------------------------------------
#### select
### select
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
@ -814,7 +814,7 @@ select &lt;symbol&gt; \[if &lt;expr&gt;\]
--------------------------------------------------------------------------------
#### source
### source
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'
@ -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
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:
- defconfig_list
@ -944,7 +944,7 @@ statements:
#define SYMBOL NAME XXX
#### Symbol types:
##### Symbol types:
- bool, int, and hex types - Every symbol of one of these types created in the
Kconfig tree is defined. It doesnt matter whether theyre in an if/endif
block, or have a depends on statement - they ALL end up being defined in
@ -963,7 +963,7 @@ variable. This is not set in coreboot, which uses the default CONFIG_ prefix
for all of its symbols.
The coreboot makefile forces the config.h file to be included into all coreboot
C files. This is done in Makefile.mk on the compiler command line using the
C files. This is done in Makefile.inc on the compiler command line using the
“-include $(obj)/config.h” command line option.
Example of various symbol types in the config.h file:
@ -1160,25 +1160,29 @@ saved .config file. As always, a 'select' statement overrides any specified
- coreboot has added the glob operator '*' for the 'source' keyword.
- coreboots Kconfig always defines variables except for strings. In other
Kconfig implementations, bools set to false/0/no are not defined.
- coreboots version of Kconfig adds the KCONFIG_STRICT environment variable to
error out if there are any issues in the Kconfig files. In the Linux kernel,
Kconfig will generate a warning, but will still output an updated .config or
config.h file.
## Kconfig Editor Highlighting
### vim:
#### vim:
vim has syntax highlighting for Kconfig built in (or at least as a part of
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:
@ -1217,7 +1221,7 @@ in.
## License:
This work is licensed under the Creative Commons Attribution 4.0 International
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.
Code examples snippets are licensed under GPLv2, and are used here under fair

View file

@ -14,13 +14,18 @@ coreboot uses [Sphinx] documentation tool. We prefer the markdown format
over reStructuredText so only embedded ReST is supported. Checkout the
[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.
To build the image run the following in the base directory:
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:
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>.
### Option 2: Install Sphinx
### option 2: Install Sphinx
Please follow this official [guide] to install sphinx. You will also need
myst-parser for sphinx to be able to handle markdown documentation.
Please follow this official [guide] to install sphinx.
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,
the installation via pip in a venv is recommended. You'll need these python3
modules:
* sphinx
* myst-parser
* sphinx-rtd-theme
* recommonmark
* sphinx_rtd_theme
* sphinxcontrib-ditaa
The following combination of versions has been tested: sphinx 8.1.3,
myst-parser 4.0.0, and sphinx-rtd-theme 2.0.0.
The following combination of versions has been tested: sphinx 2.3.1,
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
this command in there
make
make sphinx
If no error occurs, you can find the generated HTML documentation in
`Documentation/_build/html` now.
`Documentation/_build` now.
### Optional
@ -82,19 +89,17 @@ Documentation:
12. Shouldn't cover implementation details; for details, the code is the
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 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 |
|------------|-----------|-----------|
| 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}
```eval_rst
+------------+------------+-----------+
| 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
must reference each document from at least one *toctree*. The *toctree* must
only reference files in the same folder or in subfolders !
To create a toctree, you must use the following syntax to invoke the
Sphinx toctree directive:
To create a toctree, simply use a bullet list or numbered list with a single
reference. References in regular text aren't considered as *toctree* .
This feature is enabled by recommonmark's *enable_auto_toc_tree* .
**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>
Subchapter <sub/index.md>
```
References in regular text aren't considered as *toctree* .
```
1. [Chapter 1](chapter1.md)
2. [Chapter 2](chapter2.md)
```
If you do only reference the document, but do not include it in any toctree,
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
readable tables, using the following reStructuredText snipped:
```{eval-rst}
```eval_rst
.. csv-table::
:header: "Key", "Value"
: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
TOC tree.
[sphinx-autobuild]: https://github.com/sphinx-doc/sphinx-autobuild
[guide]: https://www.sphinx-doc.org/en/master/usage/installation.html
[Sphinx]: https://www.sphinx-doc.org/en/master/
[coreboot]: https://coreboot.org
[Documentation]: https://review.coreboot.org/cgit/coreboot.git/tree/Documentation
[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/
[Gerrit Guidelines]: ../contributing/gerrit_guidelines.md
[review.coreboot.org]: https://review.coreboot.org

View file

@ -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
`PP_ON_DELAYS`, `PP_OFF_DELAYS` and `PP_DIVISOR` for your `devicetree.cb`:
```{eval-rst}
```eval_rst
+-----------------------------+---------------------------------------+-----+
| Intel docs | devicetree.cb | eDP |
+-----------------------------+---------------------------------------+-----+

View file

@ -22,14 +22,14 @@ GMA: Framebuffer Configuration
*coreboot* supports two different framebuffer setups. The default
enables the legacy VGA plane in textmode. Due to legacy hardware
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
native resolution of the display if only one is detected, or the
smallest of all resolutions (per dimension) if multiple displays
are detected. This option is selected by
`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
native resolution while keeping aspect ratio.

View file

@ -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
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 coreboots 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
coreboot is primarily developed in the
@ -209,39 +170,34 @@ for example OpenBSD, is probably the closest cousin of our approach.
Contents:
```{toctree}
:maxdepth: 1
Getting Started <getting_started/index.md>
Tutorial <tutorial/index.md>
Contributing <contributing/index.md>
Community <community/index.md>
Payloads <payloads.md>
Distributions <distributions.md>
Technotes <technotes/index.md>
Internal APIs & Configuration <internals/index.md>
ACPI <acpi/index.md>
Native Graphics Initialization with libgfxinit <gfx/libgfxinit.md>
Display panel <gfx/display-panel.md>
CPU Architecture <arch/index.md>
Platform independent drivers <drivers/index.md>
Northbridge <northbridge/index.md>
System on Chip <soc/index.md>
Mainboard <mainboard/index.md>
Payloads <lib/payloads/index.md>
Libraries <lib/index.md>
Options <lib/option.md>
Security <security/index.md>
SuperIO <superio/index.md>
Vendorcode <vendorcode/index.md>
Utilities <util.md>
Software Bill of Materials <sbom/sbom.md>
Project infrastructure & services <infrastructure/index.md>
Boards supported in each release directory <releases/boards_supported_on_branches.md>
Release notes <releases/index.md>
Acronyms & Definitions <acronyms.md>
External Resources <external_docs.md>
Documentation License <documentation_license.md>
```
* [Getting Started](getting_started/index.md)
* [Tutorial](tutorial/index.md)
* [Contributing](contributing/index.md)
* [Community](community/index.md)
* [Payloads](payloads.md)
* [Distributions](distributions.md)
* [Technotes](technotes/index.md)
* [ACPI](acpi/index.md)
* [Native Graphics Initialization with libgfxinit](gfx/libgfxinit.md)
* [Display panel](gfx/display-panel.md)
* [CPU Architecture](arch/index.md)
* [Platform independent drivers](drivers/index.md)
* [Northbridge](northbridge/index.md)
* [System on Chip](soc/index.md)
* [Mainboard](mainboard/index.md)
* [Payloads](lib/payloads/index.md)
* [Libraries](lib/index.md)
* [Options](lib/option.md)
* [Security](security/index.md)
* [SuperIO](superio/index.md)
* [Vendorcode](vendorcode/index.md)
* [Utilities](util.md)
* [Software Bill of Materials](sbom/sbom.md)
* [Project infrastructure & services](infrastructure/index.md)
* [Boards supported in each release directory](releases/boards_supported_on_branches.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/

View file

@ -1,52 +0,0 @@
# Operating our services
## Mailing list moderation
Our [mailing lists] experience the same barrage of spam mails than any
other email address. We do have a spam filter in front of it, and
since the lists require registration, spam ends up in the moderation
queue. But not only spam ends up there, sometimes users send inquiries
without registering first. It's a custom of the project to let these
through, so that such emails can be discussed. This requires manual
intervention.
This section describes the tasks related to mailing list management.
### Registration
To participate in mailing list moderation, you need to become a list
moderator or owner. This is up for the existing owners to handle and
if you want to contribute in that area, it might be best to bring it
up at the leadership meeting.
After gaining leadership approval, list admins can add you to the
appropriate group in the [mailing list backend] by selecting the list,
then User / group-name, and add your email address there.
### Regular tasks
Most of our lists are auto-subscribing, so users can register
themselves and finish the process by responding to the double-opt-in
email. Some lists are manually managed though. The [mailing list
backend] shows the number of open subscription requests for these
lists on the mailing list's main page.
It also provides a list of held messages, where they can be accepted,
rejected or dropped. Spam should be dropped, that's clear. Emails with
huge attachments (e.g. screenshots) should be rejected, which gives
you an opportunity to explain the reason (in case of large
attachments, something like "Please re-send without attachments, offer
the files through some other mechanism please: Our emails are
distributed to hundreds of readers, and sending the files to everybody
is inconsiderate of traffic and storage constraints.")
Legit emails (often simple requests of the form "is this or that
supported") can be accepted, which means they'll be sent out.
If you notice recurring spam sources (e.g. marketers) you can put them
on the [global ban list] to filter them out across all lists. It takes
entries in regular expression format.
[mailing lists]: https://mail.coreboot.org/hyperkitty/
[mailing list backend]: https://mail.coreboot.org/postorius/
[global ban list]: https://mail.coreboot.org/postorius/bans/

View file

@ -23,6 +23,8 @@ as the system can just be disabled until someone is available to fix any
issues.
Currently active Jenkins admins:
* Patrick Georgi:
* Email: [patrick@coreboot.org](mailto:patrick@coreboot.org)
* Martin Roth:
* Email: [gaumless@gmail.com](mailto:gaumless@gmail.com)
* IRC: martinr

View file

@ -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
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.

View file

@ -4,17 +4,9 @@ This section contains documentation about our infrastructure
## Services
```{toctree}
:maxdepth: 1
* [Project services](services.md)
Project services <services.md>
Administrator's handbook <admin.md>
```
## Jenkins builders and builds
```{toctree}
:maxdepth: 1
Setting up Jenkins build machines <builders.md>
Coverity Scan integration <coverity.md>
```
* [Setting up Jenkins build machines](builders.md)
* [Coverity Scan integration](coverity.md)

View file

@ -41,7 +41,7 @@ stating:
### Gerrit user avatar
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)).
The image must be provided in JPEG format, must be square and have at most 50000
bytes.

View file

@ -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.

View file

@ -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.

View file

@ -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

View file

@ -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>
```

View file

@ -2,284 +2,225 @@
## Motivation
The firmware configuration interface in coreboot is designed to support
a wide variety of configuration options in that are dictated by the
hardware at runtime. This allows a single BIOS image to be used across a
wide variety of devices which may have key differences but are otherwise
similar enough to use the same coreboot build target.
The firmware configuration interface in coreboot is designed to support a wide variety of
configuration options in that are dictated by the hardware at runtime. This allows a single
BIOS image to be used across a wide variety of devices which may have key differences but are
otherwise similar enough to use the same coreboot build target.
The initial implementation is designed to take advantage of a bitmask
returned by the Embedded Controller on Google ChromeOS devices which
allows the manufacturer to use the same firmware image across multiple
devices by selecting various options at runtime. See the ChromiumOS
The initial implementation is designed to take advantage of a bitmask returned by the Embedded
Controller on Google ChromeOS devices which allows the manufacturer to use the same firmware
image across multiple devices by selecting various options at runtime. See the ChromiumOS
[Firmware Config][1] documentation for more information.
This firmware configuration interface differs from the CMOS option
interface in that this bitmask value is not intended as a
user-configurable setting as the configuration values must match the
actual hardware. In the case where a user was to swap their hardware
this value would need to be updated or overridden.
This firmware configuration interface differs from the CMOS option interface in that this
bitmask value is not intended as a user-configurable setting as the configuration values must
match the actual hardware. In the case where a user was to swap their hardware this value
would need to be updated or overridden.
## Device Presence
One common example of why a firmware configuration interface is
important is determining if a device is present in the system. With some
bus topologies and hardware mechanisms it is possible to probe and
enumerate this at runtime:
One common example of why a firmware configuration interface is important is determining if a
device is present in the system. With some bus topologies and hardware mechanisms it is
possible to probe and enumerate this at runtime:
- 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.
- The use of GPIOs with external strap to ground or different voltages
can be used to detect presence of a device.
- The use of GPIOs with external strap to ground or different voltages can be used to detect
presence of a device.
However there are several cases where this is insufficient:
- I2C peripherals that require different drivers but have the same bus
address cannot be uniquely identified at runtime.
- A mainboard may be designed with multiple daughter board combinations
which contain devices and configurations that cannot be detected.
- While presence detect GPIOs are a convenient way for a single device
presence, they are unable to distinguish between different devices so
it can require a large number of GPIOs to support relatively few
options.
- I2C peripherals that require different drivers but have the same bus address cannot be
uniquely identified at runtime.
- A mainboard may be designed with multiple daughter board combinations which contain devices
and configurations that cannot be detected.
- While presence detect GPIOs are a convenient way for a single device presence, they are
unable to distinguish between different devices so it can require a large number of GPIOs to
support relatively few options.
This presence detection can impact different stages of boot:
### ACPI
Devices that are not present should not provide an ACPI device
indicating that they are present or the operating system may not be able
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.
Devices that are not present should not provide an ACPI device indicating that they are
present or the operating system may not be able 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.
### GPIO
GPIOs with multiple functions may need to be configured correctly
depending on the attached device. Given the wide variety of GPIO
configuration possibilities it is not feasible to specify all
combinations directly in `devicetree.cb` and it is best left to code
provided by the mainboard.
GPIOs with multiple functions may need to be configured correctly depending on the attached
device. Given the wide variety of GPIO configuration possibilities it is not feasible to
specify all combinations directly in `devicetree.cb` and it is best left to code provided by
the mainboard.
### FSP UPD
Enabling and disabling devices may require altering FSP UPD values that
are provided to the various stages of FSP. These options are also not
easy to specify multiple times for different configurations in
`devicetree.cb` and can be provided by the mainboard as code.
Enabling and disabling devices may require altering FSP UPD values that are provided to the
various stages of FSP. These options are also not easy to specify multiple times for
different configurations in `devicetree.cb` and can be provided by the mainboard as code.
## Firmware Configuration Interface
The firmware configuration interface can be enabled by selecting
`CONFIG_FW_CONFIG` and also providing a source for the value by defining
an additional Kconfig option defined below.
If the firmware configuration interface is disabled via Kconfig then all
probe attempts will return true.
The firmware configuration interface can be enabled by selecting `CONFIG_FW_CONFIG` and also
providing a source for the value by defining an additional Kconfig option defined below.
If the firmware configuration interface is disabled via Kconfig then all probe attempts will
return true.
## Firmware Configuration Value
The 64-bit value used as the firmware configuration bitmask is meant to
be determined at runtime but could also be defined at compile time if
needed.
There are two supported sources for providing this information to
coreboot.
The 64-bit value used as the firmware configuration bitmask is meant to be determined at runtime
but could also be defined at compile time if needed.
There are two supported sources for providing this information to coreboot.
### CBFS
The value can be provided with a 64-bit raw value in CBFS that is read
by coreboot. The value can be set at build time but also adjusted in an
existing image with `cbfstool`.
The value can be provided with a 64-bit raw value in CBFS that is read by coreboot. The value
can be set at build time but also adjusted in an existing image with `cbfstool`.
To enable this select the `CONFIG_FW_CONFIG_CBFS` option in the build
configuration and add a raw 64-bit value to CBFS with the name of the
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.
To enable this select the `CONFIG_FW_CONFIG_CBFS` option in the build configuration and add a
raw 64-bit value to CBFS with the name of the 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.
### Embedded Controller
Google ChromeOS devices support an Embedded Controller interface for
reading and writing the firmware configuration value, along with other
board-specific information. It is possible for coreboot to read this
value at boot on systems that support this feature.
Google ChromeOS devices support an Embedded Controller interface for reading and writing the
firmware configuration value, along with other board-specific information. It is possible for
coreboot to read this value at boot on systems that support this feature.
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
adjust the value. It is possible by enabling the CBFS source and
coreboot will look in CBFS first for a valid value before asking the
embedded controller.
`CONFIG_FW_CONFIG_CHROME_EC_CBI` and it is not typically necessary to adjust the value. It is
possible by enabling the CBFS source and coreboot will look in CBFS first for a valid value
before asking the embedded controller.
It is also possible to adjust the value in the embedded controller
*(after disabling write protection)* with the `ectool` command in a
ChromeOS environment.
It is also possible to adjust the value in the embedded controller *(after disabling write
protection)* with the `ectool` command in a ChromeOS environment.
For more information on the firmware configuration field on ChromeOS
devices see the Chromium documentation for [Firmware Config][1] and
[Board Info][2].
For more information on the firmware configuration field on ChromeOS devices see the Chromium
documentation for [Firmware Config][1] and [Board Info][2].
[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
## Firmware Configuration Table
The firmware configuration table itself is defined in the mainboard
`devicetree.cb` with special tokens for defining fields and options.
The firmware configuration table itself is defined in the mainboard `devicetree.cb` with
special tokens for defining fields and options.
The table itself is enclosed in a `fw_config` token and terminated with
`end` and it contains a mix of field and option definitions.
The table itself is enclosed in a `fw_config` token and terminated with `end` and it contains
a mix of field and option definitions.
Each field is defined by providing the field name and the start and end
bit marking the exact location in the bitmask. Field names must be at
least three characters long in order to satisfy the sconfig parser
requirements and they must be unique with non-overlapping masks.
Each field is defined by providing the field name and the start and end bit marking the exact
location in the bitmask. Field names must be at least three characters long in order to
satisfy the sconfig parser 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:
```text
field <name> <bit> [option...] end
```
field <name> <bit> [option...] end
A field definition can also contain multiple sets of bit masks, which
can be dis-contiguous. They are treated as if they are contiguous when
defining option values. This allows for extending fields even after the
bits after its current masks are occupied.
A field definition can also contain multiple sets of bit masks, which can be dis-contiguous.
They are treated as if they are contiguous when defining option values. This allows for
extending fields even after the 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:
```text
field AUDIO 3 3
option AUDIO_0 0
option AUDIO_1 1
end
field OTHER 4 4
...
end
```
field AUDIO 3 3
option AUDIO_0 0
option AUDIO_1 1
end
field OTHER 4 4
...
end
the following can be done:
```text
field AUDIO 3 3 | 5 5
option AUDIO_FOO 0
option AUDIO_BLAH 1
option AUDIO_BAR 2
option AUDIO_BAZ 3
end
field OTHER 4 4
...
end
```
field AUDIO 3 3 | 5 5
option AUDIO_FOO 0
option AUDIO_BLAH 1
option AUDIO_BAR 2
option AUDIO_BAZ 3
end
field OTHER 4 4
...
end
In that case, the AUDIO masks are extended like so:
```c
#define FW_CONFIG_FIELD_AUDIO_MASK 0x28
#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_BAR_VALUE 0x20
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_BAz_VALUE 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_BLAH_VALUE 0x8
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_BAR_VALUE 0x20
#define FW_CONFIG_FIELD_AUDIO_OPTION_AUDIO_BAz_VALUE 0x28
Each `field` definition starts a new block that can be composed of zero
or more field options, and it is terminated with `end`.
Each `field` definition starts a new block that can be composed of zero or more field options,
and it is terminated with `end`.
Inside the field block the options can be defined by providing the
option name and the field value that this option represents when the bit
offsets are used to apply a mask and shift. Option names must also be at
least three characters for the sconfig parser.
Inside the field block the options can be defined by providing the option name and the field
value that this option represents when the bit offsets are used to apply a mask and shift.
Option names must also be at 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
subsequent `field` blocks to add additional `option` definitions to the
existing field. These subsequent definitions should not provide the
field bitmask as it has already been defined earlier in the file and
It is possible for there to be multiple `fw_config` blocks and for subsequent `field` blocks
to add additional `option` definitions to the existing field. These subsequent definitions
should not provide the field bitmask as it has already been defined earlier in the file and
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
`devicetree.cb` and a board variant to add specific options to fields in
or define new fields in the unused bitmask in `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.
This allows a baseboard to define the major fields and options in `devicetree.cb` and a board
variant to add specific options to fields in or define new fields in the unused bitmask in
`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.
### Firmware Configuration Table Example
In this example a baseboard defines a simple boolean feature that is
enabled or disabled depending on the value of bit 0, and a field at bits
1-2 that indicates which daughter board 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.
In this example a baseboard defines a simple boolean feature that is enabled or disabled
depending on the value of bit 0, and a field at bits 1-2 that indicates which daughter board
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.
#### devicetree.cb
```text
fw_config
field FEATURE 0
option DISABLED 0
option ENABLED 1
fw_config
field FEATURE 0
option DISABLED 0
option ENABLED 1
end
field DAUGHTER_BOARD 1 2
option NONE 0
option REFERENCE_DB 1
end
end
field DAUGHTER_BOARD 1 2
option NONE 0
option REFERENCE_DB 1
end
end
```
#### overridetree.cb
```text
fw_config
field DAUGHTER_BOARD
option VARIANT_DB_ONE 2
option VARIANT_DB_TWO 3
fw_config
field DAUGHTER_BOARD
option VARIANT_DB_ONE 2
option VARIANT_DB_TWO 3
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
@ -305,96 +246,73 @@ field mask and the option value.
#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_VALUE 0x00000006
```
## Device Probing
One use of the firmware configuration interface in devicetree is to
allow device probing to be specified directly with the devices
themselves. A new `probe` token is introduced to allow a device to be
probed by field and option name. Multiple `probe` entries may be present
for each device and any successful probe will consider the device to be
present.
One use of the firmware configuration interface in devicetree is to allow device probing to be
specified directly with the devices themselves. A new `probe` token is introduced to allow a
device to be probed by field and option name. Multiple `probe` entries may be present for
each device and any successful probe will consider the device to be present.
### Probing Example
Continuing with the previous example this device would be considered
present if the field `DAUGHTER_BOARD` was set to either `VARIANT_DB_ONE`
or `VARIANT_DB_TWO`:
Continuing with the previous example this device would be considered present if the field
`DAUGHTER_BOARD` was set to either `VARIANT_DB_ONE` or `VARIANT_DB_TWO`:
#### overridetree.cb
```text
chip drivers/generic/example
device generic 0 on
probe DAUGHTER_BOARD VARIANT_DB_ONE
probe DAUGHTER_BOARD VARIANT_DB_TWO
chip drivers/generic/example
device generic 0 on
probe DAUGHTER_BOARD VARIANT_DB_ONE
probe DAUGHTER_BOARD VARIANT_DB_TWO
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
When a device is declared with a probe in the baseboard `devicetree.cb`
and the same device is also present in the `overridetree.cb` then the
probing information from the baseboard is discarded and the override
device must provide all necessary probing information.
When a device is declared with a probe in the baseboard `devicetree.cb` and the same device
is also present in the `overridetree.cb` then the probing information from the baseboard
is discarded and the override device must provide all necessary probing information.
In this example a device is listed in the baseboard with
`DAUGHTER_BOARD` field probing for `REFERENCE_DB` as a field option, It
is also defined as an override device with the field probing for the
`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 example a device is listed in the baseboard with `DAUGHTER_BOARD` field probing for
`REFERENCE_DB` as a field option, It is also defined as an override device with the field
probing for the `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.
#### devicetree.cb
```text
chip drivers/generic/example
device generic 0 on
probe DAUGHTER_BOARD REFERENCE_DB
end
end
```
chip drivers/generic/example
device generic 0 on
probe DAUGHTER_BOARD REFERENCE_DB
end
end
#### overridetree.cb
```text
chip drivers/generic/example
device generic 0 on
probe DAUGHTER_BOARD VARIANT_DB_ONE
end
end
```
chip drivers/generic/example
device generic 0 on
probe DAUGHTER_BOARD VARIANT_DB_ONE
end
end
### Automatic Device Probing
At boot time the firmware configuration interface will walk the device
tree and apply any probe entries that were defined in `devicetree.cb`.
This probing takes effect before the `BS_DEV_ENUMERATE` step during the
boot state machine in ramstage.
At boot time the firmware configuration interface will walk the device tree and apply any
probe entries that were defined in `devicetree.cb`. This probing takes effect before the
`BS_DEV_ENUMERATE` step during the boot state machine in ramstage.
Devices that have a probe list but do do not find a match are disabled
by setting `dev->enabled = 0` but the chip `enable_dev()` and device
`enable()` handlers will still be executed to allow any device disable
code to execute.
The result of this probe definition is to provide an array of structures
describing each field and option to check.
Devices that have a probe list but do do not find a match are disabled by setting
`dev->enabled = 0` but the chip `enable_dev()` and device `enable()` handlers will still
be executed to allow any device disable code to execute.
The result of this probe definition is to provide an array of structures describing each
field and option to check.
#### fw_config.h
@ -407,43 +325,40 @@ describing each field and option to check.
* @value: Value of the option within the mask.
*/
struct fw_config {
const char *field_name;
const char *option_name;
uint64_t mask;
uint64_t value;
const char *field_name;
const char *option_name;
uint64_t mask;
uint64_t value;
};
```
#### static.c
```c
STORAGE struct fw_config __devN_probe_list[] = {
{
.field_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_NAME,
.option_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_NAME,
.mask = FW_CONFIG_FIELD_DAUGHTER_BOARD_MASK,
.value = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_VALUE
},
{
.field_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_NAME,
.option_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_NAME,
.mask = FW_CONFIG_FIELD_DAUGHTER_BOARD_MASK,
.value = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_VALUE
},
{ }
{
.field_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_NAME,
.option_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_NAME,
.mask = FW_CONFIG_FIELD_DAUGHTER_BOARD_MASK,
.value = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_VALUE
},
{
.field_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_NAME,
.option_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_NAME,
.mask = FW_CONFIG_FIELD_DAUGHTER_BOARD_MASK,
.value = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_VALUE
},
{ }
};
```
### Runtime Probing
The device driver probing allows for seamless integration with the
mainboard but it is only effective in ramstage and for specific devices
declared in devicetree.cb. There are other situations where code may
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 interface directly.
The device driver probing allows for seamless integration with the mainboard but it is only
effective in ramstage and for specific devices declared in devicetree.cb. There are other
situations where code may 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
interface directly.
```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:
```text
FW_CONFIG(field, option)
```
FW_CONFIG(field, option)
This example has a mainboard check if a feature is disabled and set an
FSP UPD before memory training. This example expects that the default
value of this `register` is set to `true` in `devicetree.cb` and this
code is disabling that feature before FSP is executed.
This example has a mainboard check if a feature is disabled and set an FSP UPD before memory
training. This example expects that the default value of this `register` is set to `true` in
`devicetree.cb` and this code is disabling that feature before FSP is executed.
```c
#include <fw_config.h>
void mainboard_memory_init_params(FSPM_UPD *mupd)
{
if (fw_config_probe(FW_CONFIG(FEATURE, DISABLED))
mupd->ExampleFeature = false;
if (fw_config_probe(FW_CONFIG(FEATURE, DISABLED))
mupd->ExampleFeature = false;
}
```

View file

@ -3,15 +3,7 @@
This section contains documentation about coreboot internal technical
information and libraries.
```{toctree}
:maxdepth: 1
Flashmap and Flashmap Descriptor <flashmap.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>
```
- [Flashmap and Flashmap Descriptor](flashmap.md)
- [ABI data consumption](abi-data-consumption.md)
- [Timestamps](timestamp.md)
- [Firmware Configuration Interface](fw_config.md)

View file

@ -8,8 +8,4 @@ selected mainboard.
## FIT
```{toctree}
:maxdepth: 1
uImage.FIT support <fit.md>
```
- [uImage.FIT support](fit.md)

View file

@ -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.

View file

@ -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.

View file

@ -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`).

View file

@ -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.

View file

@ -2,408 +2,175 @@
## Introduction
The aim of the timestamp library is to make it easier for different
boards to save timestamps in cbmem / stash (until cbmem is brought up)
by providing a simple API to initialize, add, and sync timestamps. In
order to make the timestamps persistent and accessible from the kernel,
we need to ensure that all the saved timestamps end up in cbmem under
The aim of the timestamp library is to make it easier for different boards
to save timestamps in cbmem / stash (until cbmem is brought up) by
providing a simple API to initialize, add and sync timestamps. In order
to make the timestamps persistent and accessible from the kernel, we
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 timestamps can be saved to a SoC-defined `_timestamp` region if one
is defined in the board's `memlayout.ld`. The work of identifying the
right location for storing timestamps is done by the library and is not
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.
the timestamps can be saved to a SoC-defined \_timestamp region or in a
local stage-specific stash. The work of identifying the right location for
storing timestamps is done by the library and is not exposed to the user.
Working of timestamp library from a user perspective can be outlined in
the following steps:
1. Initialize the base time and reset cbmem timestamp area using
`timestamp_init()`.
2. Start adding timestamps using `timestamp_add()` or
`timestamp_add_now()`.
1. Initialize the base time and reset cbmem timestamp area
2. Start adding timestamps
Behind the scenes, the timestamp library takes care of:
1. Identifying the correct location for storing timestamps (`_timestamp`
region before cbmem is ready, then cbmem region).
2. Add a new cbmem timestamp area based on whether a reset of the cbmem
1. Identifying the correct location for storing timestamps (cbmem or timestamp
region or local stash).
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.
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
functions are implemented as no-ops, and no timestamps will be
collected.
### Transition from cache to cbmem
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
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`.
## Data structures used
The main structure that maintains information about the timestamp cache is:
```c
struct timestamp_entry {
uint32_t entry_id;
int64_t entry_stamp;
} __packed;
struct __packed timestamp_cache {
uint16_t cache_state;
struct timestamp_table table;
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
struct timestamp_table {
uint64_t base_time;
uint16_t max_entries;
uint16_t tick_freq_mhz;
uint32_t num_entries;
struct timestamp_entry entries[]; /* Variable number of entries */
uint64_t base_time;
uint32_t max_entries;
uint32_t num_entries;
struct timestamp_entry entries[0]; /* Variable number of entries */
} __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 in this table.
- `max_entries`: Maximum number of entries that can be stored in this
table instance.
- `tick_freq_mhz`: Timestamp tick frequency in MHz. Populated later in
boot.
- `num_entries`: Total number of entries that currently exist in this
table instance.
- `entries`: Array holding the actual timestamp entries.
### entries
This field holds the details of each timestamp entry, up to a maximum
of `MAX_TIMESTAMP_CACHE` which is defined as 16 entries. Each entry is
defined by:
```c
struct timestamp_entry {
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
Timestamps are stored in two locations during the boot process:
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`.
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
`base_time`, `max_entries` (which is 30), current number of entries and the
actual entries represented by `timestamp_entry`.
## 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
void timestamp_init(uint64_t base);
```
>>> _Source: `/src/include/timestamp.h`_
### timestamp_add
Initializes the timestamp system with a base time. This function sets up
the timestamp cache (`_timestamp` region) and should be run in
bootblock. It must be called once in *one* of the
`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().
This function accepts from user a timestamp id and time to record in the
timestamp table. It stores the entry in the appropriate table in cbmem
or `_timestamp` region or local stash.
#### timestamp_add
### timestamp_add_now
```c
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.
This function calls `timestamp_add` with user-provided id and current time.
## Use / Test Cases
The following cases describe the behavior based on the presence of the
`timestamp` region and when cbmem is initialized.
The following cases have been considered while designing the timestamp
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.
`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.
All regions are automatically reset on initialization.
### 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
`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.
### Case 3: No timestamp region, fresh boot, cbmem_initialize called before timestamp_init
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.
If `ENV_CREATES_CBMEM` is true for the resume path (as it is for x86
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.
We always reset the cbmem region before using it, so pre-suspend timestamps
will be gone.
### Case 5: No timestamp region, resume, cbmem_initialize called before timestamp_init
## Configuration
### 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`.
We always reset the cbmem region before using it, so pre-suspend timestamps
will be gone.

View file

@ -5,7 +5,7 @@ Acer models Aspire M3800, Aspire M5800 and possibly more.
## Technology
```{eval-rst}
```eval_rst
+------------------+--------------------------------------------------+
| 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
```{eval-rst}
```eval_rst
+-------------------+---------------------+
| Type | Value |
+===================+=====================+
@ -122,8 +122,10 @@ $ sudo flashrom \
-w coreboot.rom
```
```eval_rst
In addition to the information here, please see the
<project:../../tutorial/flashing_firmware/index.md>.
:doc:`../../tutorial/flashing_firmware/index`.
```
### External flashing

View file

@ -33,7 +33,7 @@ Three items are marked in this picture
## Flashing coreboot
```{eval-rst}
```eval_rst
+---------------------+--------------------+
| Type | Value |
+=====================+====================+
@ -53,7 +53,7 @@ Three items are marked in this picture
## Technology
```{eval-rst}
```eval_rst
+---------------+------------------------------+
| Fan control | Using fintek F81803A |
+---------------+------------------------------+
@ -63,7 +63,7 @@ Three items are marked in this picture
## Description of pictures within this document
```{eval-rst}
```eval_rst
+----------------------------+----------------------------------------+
|pademelon.jpg | Motherboard with components identified |
+----------------------------+----------------------------------------+

View file

@ -11,7 +11,7 @@ Intel company provides [Firmware Support Package (2.0)](../../soc/intel/fsp/inde
FSP Information:
```{eval-rst}
```eval_rst
+-----------------------------+-------------------+-------------------+
| FSP Project Name | Directory | Specification |
+-----------------------------+-------------------+-------------------+
@ -114,7 +114,7 @@ facing towards the bottom of the board.
## Technology
```{eval-rst}
```eval_rst
+------------------+--------------------------------------------------+
| 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/
[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

View file

@ -5,7 +5,7 @@ Bridge and Ivy Bridge CPUs.
## Technology
```{eval-rst}
```eval_rst
+------------------+--------------------------------------------------+
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
+------------------+--------------------------------------------------+
@ -71,7 +71,7 @@ extlinux
## Flashing coreboot
```{eval-rst}
```eval_rst
+---------------------+------------+
| 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
region is not readable even by the host.
```eval_rst
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

View file

@ -4,7 +4,9 @@ This page describes how to run coreboot on the [ASRock H81M-HDS].
## Required proprietary blobs
Please see <project:../../northbridge/intel/haswell/mrc.bin.md>.
```eval_rst
Please see :doc:`../../northbridge/intel/haswell/mrc.bin`.
```
## 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
temperature readings from an OS.
Please also see
<project:../../northbridge/intel/haswell/known-issues.md>.
```eval_rst
Please also see :doc:`../../northbridge/intel/haswell/known-issues`.
```
## Untested
@ -108,7 +111,7 @@ Please also see
## Technology
```{eval-rst}
```eval_rst
+------------------+--------------------------------------------------+
| Northbridge | :doc:`../../northbridge/intel/haswell/index` |
+------------------+--------------------------------------------------+
@ -126,5 +129,5 @@ Please also see
[ASRock H81M-HDS]: https://www.asrock.com/mb/Intel/H81M-HDS/
[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

View file

@ -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/

View file

@ -14,7 +14,7 @@ and their GPU is [Sea Islands] (GCN2-based).
A10 Richland is recommended for the best performance and working IOMMU.
```{eval-rst}
```eval_rst
+------------------+--------------------------------------------------+
| A88XM-E | |
+------------------+--------------------------------------------------+
@ -36,7 +36,7 @@ A10 Richland is recommended for the best performance and working IOMMU.
## Flashing coreboot
```{eval-rst}
```eval_rst
+---------------------+------------+
| Type | Value |
+=====================+============+
@ -162,7 +162,7 @@ Tested even with/without the Bolton and Hudson blobs.
[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
[flashrom]: https://flashrom.org/
[flashrom]: https://flashrom.org/Flashrom
[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
[Sea Islands]: https://en.wikipedia.org/wiki/Graphics_Core_Next#GCN_2nd_generation

View file

@ -15,7 +15,7 @@ Both "Trinity" and "Richland" desktop processing units are working,
the CPU architecture in these CPUs/APUs is [Piledriver],
and their GPU is [TeraScale 3] (VLIW4-based).
```{eval-rst}
```eval_rst
+------------------+--------------------------------------------------+
| F2A85-M | |
+------------------+--------------------------------------------------+
@ -35,7 +35,7 @@ and their GPU is [TeraScale 3] (VLIW4-based).
+------------------+--------------------------------------------------+
```
```{eval-rst}
```eval_rst
+------------------+--------------------------------------------------+
| F2A85-M LE | |
+------------------+--------------------------------------------------+
@ -55,7 +55,7 @@ and their GPU is [TeraScale 3] (VLIW4-based).
+------------------+--------------------------------------------------+
```
```{eval-rst}
```eval_rst
+------------------+--------------------------------------------------+
| F2A85-M PRO | |
+------------------+--------------------------------------------------+
@ -77,7 +77,7 @@ and their GPU is [TeraScale 3] (VLIW4-based).
## Flashing coreboot
```{eval-rst}
```eval_rst
+---------------------+------------+
| 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/
[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
[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

View file

@ -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

View file

@ -10,7 +10,7 @@ This page describes how to run coreboot on the ASUS P2B-LS mainboard.
## Flashing coreboot
```{eval-rst}
```eval_rst
+---------------------+---------------------------+
| Type | Value |
+=====================+===========================+
@ -90,7 +90,7 @@ for only CPU models that the board will actually be run with.
## Technology
```{eval-rst}
```eval_rst
+------------------+--------------------------------------------------+
| Northbridge | Intel I440BX |
+------------------+--------------------------------------------------+
@ -105,4 +105,4 @@ for only CPU models that the board will actually be run with.
## Extra resources
[flashrom]: https://flashrom.org/
[flashrom]: https://flashrom.org/Flashrom

View file

@ -4,7 +4,7 @@ This page describes how to run coreboot on the ASUS P3B-F mainboard.
## Flashing coreboot
```{eval-rst}
```eval_rst
+---------------------+---------------------------+
| Type | Value |
+=====================+===========================+
@ -88,7 +88,7 @@ for only CPU models that the board will actually be run with.
## Technology
```{eval-rst}
```eval_rst
+------------------+--------------------------------------------------+
| Northbridge | Intel I440BX |
+------------------+--------------------------------------------------+
@ -103,4 +103,4 @@ for only CPU models that the board will actually be run with.
## Extra resources
[flashrom]: https://flashrom.org/
[flashrom]: https://flashrom.org/Flashrom

View file

@ -32,7 +32,7 @@ This page describes how to run coreboot on the [ASUS P5Q] desktop board.
## Flashing coreboot
```{eval-rst}
```eval_rst
+-------------------+----------------+
| Type | Value |
+===================+================+
@ -56,7 +56,7 @@ You can flash coreboot into your motherboard using [this guide].
## Technology
```{eval-rst}
```eval_rst
+------------------+---------------------------------------------------+
| Northbridge | Intel P45 (called x4x in coreboot code) |
+------------------+---------------------------------------------------+

View file

@ -4,7 +4,7 @@ This page describes how to run coreboot on the [ASUS P8H77-V].
## Flashing coreboot
```{eval-rst}
```eval_rst
+---------------------+----------------+
| Type | Value |
+=====================+================+
@ -69,7 +69,7 @@ flash externally.
## Technology
```{eval-rst}
```eval_rst
+------------------+--------------------------------------------------+
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
+------------------+--------------------------------------------------+
@ -91,4 +91,4 @@ flash externally.
[ASUS P8C WS]: https://www.asus.com/supportonly/p8c_ws/helpdesk_knowledge/
[W25Q64FVA1Q]: https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf
[flashrom]: https://flashrom.org/
[flashrom]: https://flashrom.org/Flashrom

View file

@ -4,7 +4,7 @@ This page describes how to run coreboot on the [ASUS P8H61-M LX].
## Flashing coreboot
```{eval-rst}
```eval_rst
+---------------------+------------+
| Type | Value |
+=====================+============+
@ -84,7 +84,7 @@ region is not readable even by the host.
## Technology
```{eval-rst}
```eval_rst
+------------------+--------------------------------------------------+
| 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/
[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

View file

@ -4,7 +4,7 @@ This page describes how to run coreboot on the [ASUS P8H61-M Pro].
## Flashing coreboot
```{eval-rst}
```eval_rst
+---------------------+------------+
| Type | Value |
+=====================+============+
@ -78,7 +78,7 @@ region is not readable even by the host.
## Technology
```{eval-rst}
```eval_rst
+------------------+--------------------------------------------------+
| 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/
[W25Q32BV]: https://www.winbond.com/resource-files/w25q32bv_revi_100413_wo_automotive.pdf
[flashrom]: https://flashrom.org/
[flashrom]: https://flashrom.org/Flashrom

View file

@ -4,7 +4,7 @@ This page describes how to run coreboot on the [ASUS P8H77-V].
## Flashing coreboot
```{eval-rst}
```eval_rst
+---------------------+----------------+
| Type | Value |
+=====================+================+
@ -56,7 +56,7 @@ work. The flash chip is socketed, so it's easy to remove and reflash.
## Technology
```{eval-rst}
```eval_rst
+------------------+--------------------------------------------------+
| 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/
[W25Q64FVA1Q]: https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf
[flashrom]: https://flashrom.org/
[flashrom]: https://flashrom.org/Flashrom

View file

@ -4,7 +4,7 @@ This page describes how to run coreboot on the [ASUS P8Z77-M].
## Flashing coreboot
```{eval-rst}
```eval_rst
+---------------------+----------------+
| Type | Value |
+=====================+================+
@ -35,119 +35,84 @@ The flash chip is socketed, so it's easy to remove and reflash.
## Working
- 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)
- 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
(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
(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
- PCI slot
- Rockwell HSF 56k PCI modem (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
Rockwell HSF 56k PCI modem, Sound Blaster Live! CT4780 (cards detected, not function tested)
Promise SATA150 TX2plus (R/W OK to connected IDE hard drive, OpRom loaded, cannot boot from
SeaBIOS)
- PCIe x1 slot
- MSI Herald-BE (Qualcomm NCM865 m.2 Wifi 7 module via PCIe-m.2 adaptor)
- LPC POST card manually wired to TPM header
- S3 suspend from Linux
- 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
- 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
- If you use MRC raminit, the NVRAM variable gfx_uma_size may be ignored as IGP's UMA could
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.
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.
- Although the black PCIEX16_2 slot can physically fit an x16 card, it only has physical
contacts for x8, and is electrically 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
```
- The black PCIEX16_2 slot, although can physically fit an x16, only has physical contacts for
an x8, and is electrically an x4 only.
## Untested
- Wake-on-LAN
- USB3 on header
- TPM module
- TPM 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
- 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
copy of front left and right audio, and the other two channels are silent.
## RAM compatibility
### Native and MRC raminit:
## Native (and MRC) raminit compatibility
- 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.
- 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.
- 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
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
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.
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
```{eval-rst}
```eval_rst
+------------------+--------------------------------------------------+
| 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]
[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
[flashrom]: https://flashrom.org/
[flashrom]: https://flashrom.org/Flashrom

View file

@ -4,7 +4,7 @@ This page describes how to run coreboot on the [ASUS P8Z77-M PRO]
## Flashing coreboot
```{eval-rst}
```eval_rst
+---------------------+----------------+
| Type | Value |
+=====================+================+
@ -143,7 +143,7 @@ easy to remove and reflash.
## Technology
```{eval-rst}
```eval_rst
+------------------+--------------------------------------------------+
| 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/
[W25Q64FVA1Q]: https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf
[flashrom]: https://flashrom.org/
[flashrom]: https://flashrom.org/Flashrom

View file

@ -4,7 +4,7 @@ This page describes how to run coreboot on the [ASUS P8Z77-V].
## Flashing coreboot
```{eval-rst}
```eval_rst
+---------------------+----------------+
| Type | Value |
+=====================+================+
@ -86,7 +86,7 @@ See [Asus Wi-Fi Go! v1].
## Technology
```{eval-rst}
```eval_rst
+------------------+--------------------------------------------------+
| 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/
[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

View file

@ -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

View file

@ -8,7 +8,7 @@ through a proprietary 16-1 pin connector.
I managed to grope the most pinout of the proprietary connector.
See [Mini PCIe pinout] for more info.
```{eval-rst}
```eval_rst
+------------+----------+-----------+------------+----------+-----------+
| WIFIGO Pin | Usage | mPCIe pin | WIFIGO Pin | Usage | mPCIe pin |
+============+==========+===========+============+==========+===========+

View file

@ -17,7 +17,7 @@
## Flashing coreboot
```{eval-rst}
```eval_rst
+---------------------+----------------+
| Type | Value |
+=====================+================+
@ -58,7 +58,7 @@
## Technology
```{eval-rst}
```eval_rst
+---------------+----------------------------------------+
| SoC | :doc:`../../soc/cavium/cn81xx/index` |
+---------------+----------------------------------------+

View file

@ -2,7 +2,7 @@
## Hardware
### Technology
```{eval-rst}
```eval_rst
+------------------+--------------------------------+
| CPU | Intel i7-8550U |
+------------------+--------------------------------+
@ -15,7 +15,7 @@
```
### Flash chip
```{eval-rst}
```eval_rst
+---------------------+-----------------+
| Type | Value |
+=====================+=================+

View file

@ -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.
![Dell Latitude E7240 mainboard](e7240.webp)
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

View file

@ -6,7 +6,7 @@ This page describes how to run coreboot on Dell OptiPlex 9010 SFF.
## Technology
```{eval-rst}
```eval_rst
+------------+---------------------------------------------------------------+
| CPU | Intel Core 2nd Gen (Sandybridge) or 3rd Gen (Ivybridge) |
+------------+---------------------------------------------------------------+
@ -28,7 +28,7 @@ More specifications on [Dell OptiPlex 9010 specifications].
## Required proprietary blobs
```{eval-rst}
```eval_rst
+------------------+---------------------------------+---------------------+
| Binary file | Apply | Required / Optional |
+==================+=================================+=====================+
@ -50,7 +50,7 @@ signature `SMSCUBIM`. The easiest way to do this is to use [UEFITool] and
## Flashing coreboot
```{eval-rst}
```eval_rst
+---------------------+--------------------------+
| Type | Value |
+=====================+==========================+
@ -142,6 +142,6 @@ the cables or not being populated on the board case.
- Intruder detection
- 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
[UEFITool]: https://github.com/LongSoft/UEFITool

View file

@ -3,9 +3,6 @@
## Building coreboot and running it in QEMU
- Configure coreboot and run `make` as usual
Run QEMU
```
qemu-system-riscv64 -M virt -m 1G -nographic -bios build/coreboot.rom \
-drive if=pflash,file=./build/coreboot.rom,format=raw
```
- Run `util/riscv/make-spike-elf.sh build/coreboot.rom build/coreboot.elf` to
convert coreboot to an ELF that QEMU can load
- Run `qemu-system-riscv64 -M virt -m 1024M -nographic -kernel build/coreboot.elf`

Some files were not shown because too many files have changed in this diff Show more