Hi,
Studying the bios module structure I see this pattern where under the guid you have a depex section followed by another guid or a compressed section wrapping the pe32 section. In Uefitool you see on right side a lot of PUSH instructions detailed pertaining to the depex section. So I was wondering what is the relevance of all that code? I thought the depex is suppose to detail dependencies to other guids? So what it’s pushing is the guids of other dependent modules I suppose?
Thanks
You should better ask CodeRush directly than all Forum members.
Depex are dependency expression.
Wrapping the PE32 apriori, could mean these dependency will pretty much load before anything else, I’m not an expert, so don’t vouch on it
Here are some basic well written already explanation;
https://github.com/tianocore/tianocore.g…/wiki/Depex-FAQ
DEPEX section tells DXE dispatcher how one DXE driver is dependent from an other DXE driver or from any number of DXE protocols. Dependency expression (DepEx) is a list of instructions to a very simple stack machine, for example, if your DXE driver needs to be executed before a driver with a given GUID, it’s DepEx section will look like this:
BEFORE {given GUID}
END
If your Driver is using Protocol1, Protocol2 and Protocol3 and so it needs to be executed after all there will be available, it’s DepEx sections will look like this:
PUSH Protocol1Guid
PUSH Protocol2Guid
AND
PUSH Protocol3Guid
AND
END
PUSH opcode has one immediate operand - the GUID, AND opcode gets 2 GUIDs from the stack and puts TRUE (both protocols are already installed) or FALSE (one or both of the protocol is not installed) back to the stack.
For a given driver to be executed in a given round of dispatching, it’s DepEx section must evaluate to TRUE, so if the driver doesn’t depend from anything, it’s DepEx will be like this:
TRUE
END
If the driver needs to be executed by another driver, not by DXE dispatcher, this DepEx will be like this:
FALSE
END
Some drivers need to be executed even before the actual dispatching starts, they are listed in so called AprioriFile, that is a list of GUIDs of DXE drivers to run right after DxeCore without evaluating their DepEx sections.
If a driver doesn’t have DepEx section, it’s the same as if it’s TRUE; END; case, aka execute immediately.
DXE dispatcher will evaluate DepEx sections of all drivers that weren’t executed yet in rounds, if after a given round no more drives were executed, DXE phase ends and DepEx sections aren’t used anymore.
The same concept is used for PEI (instead of protocols, GUIDs of PEI-to-PEI interfaces are used there) and SMM.
Thanks for that excellent explanation. Going to print this and save for later. Thank you.
No problem. BTW, the PI spec has a comprehensive description of DepEx format and operands for each phase: http://www.uefi.org/sites/default/files/…PI_Spec_1_6.pdf
For example, PEI DepEx doesn’t support BEFORE and AFTER opcodes, but DXE and SMM variants do.
Does the same format hold for an SMM dependency section?
Because, what you say about AND having 2 operands (the last 2 items on the stack) doesn’t quite jive with what I’m seeing, e.g., in this SMM dependency section:
PUSH F4CCBFB7-F6E0-47FD-9DD4-10A8F150C191
PUSH EEE07404-26EE-43C9-9071-4E48008C4691
PUSH 6C09C5B9-BF3F-46D2-9198-4A064826F414
PUSH 18A3C6DC-5EEA-48C8-A1C1-B53389F98999
PUSH EB346B97-975F-4A9F-8B22-F8E92BB3D569
PUSH 6D7E4A32-9A73-46BA-94A1-5F2F25EF3E29
PUSH 13A3F0F6-264A-3EF0-F2E0-DEC512342F34
PUSH C2702B74-800C-4131-8746-8FB5B89CE4AC
AND
AND
AND
AND
AND
AND
AND
AND
END
That’s what I’m seeing in UEFITool, and also what I’m seeing in the dump of the binary of the section, generated by UEFI Frimware Parser:
(looks like 0x02 is PUSH, 0x03 is AND, 0x08 is END)
$hexdump -C ./regions/region-bios/volume-0/file-fb6d36a2-ef7d-4b74-99ac-80b31f6be9b1/section0.smm.depexHow would that be parsed?
00000000 02 55 9d ff db b7 89 da 46 bd df 67 7d 3d c0 24 |.U…F…g}=.$|
00000010 1d 02 b7 bf cc f4 e0 f6 fd 47 9d d4 10 a8 f1 50 |…G…P|
00000020 c1 91 02 04 74 e0 ee ee 26 c9 43 90 71 4e 48 00 |…t…&.C.qNH.|
00000030 8c 46 91 02 b9 c5 09 6c 3f bf d2 46 91 98 4a 06 |.F…l?..F…J.|
00000040 48 26 f4 14 02 dc c6 a3 18 ea 5e c8 48 a1 c1 b5 |H&…^.H…|
00000050 33 89 f9 89 99 02 97 6b 34 eb 5f 97 9f 4a 8b 22 |3…k4.…J."|
00000060 f8 e9 2b b3 d5 69 02 32 4a 7e 6d 73 9a ba 46 94 |…+…i.2J~ms…F.|
00000070 a1 5f 2f 25 ef 3e 29 02 f6 f0 a3 13 4a 26 f0 3e |./%.>)…J&.>|
00000080 f2 e0 de c5 12 34 2f 34 02 74 2b 70 c2 0c 80 31 |…4/4.t+p…1|
00000090 41 87 46 8f b5 b8 9c e4 ac 03 03 03 03 03 03 03 |A.F…|
000000a0 03 08 |…|
000000a2
Thanks!
DEPEX is a stack-based expression and result of an operation is pushed on stack again. so for example
PUSH EB346B97-975F-4A9F-8B22-F8E92BB3D569
PUSH 6D7E4A32-9A73-46BA-94A1-5F2F25EF3E29
PUSH 13A3F0F6-264A-3EF0-F2E0-DEC512342F34
PUSH C2702B74-800C-4131-8746-8FB5B89CE4AC
AND
AND
AND
is evaluated as:
PUSH 6D7E4A32-9A73-46BA-94A1-5F2F25EF3E29
PUSH (13A3F0F6-264A-3EF0-F2E0-DEC512342F34 AND C2702B74-800C-4131-8746-8FB5B89CE4AC)
AND
then:
6D7E4A32-9A73-46BA-94A1-5F2F25EF3E29 AND (13A3F0F6-264A-3EF0-F2E0-DEC512342F34 AND C2702B74-800C-4131-8746-8FB5B89CE4AC)
and so on…
So, an AND expresssion pops the last 2 items on the stack before using them as operands? (As opposed to using them as operands but leaving them on the stack)
Thanks
Yes, it pops 2 operands from the stack, logically ANDs them and pushes the result.