Dear MdeModulePkg maintainers,
We have seen on some platforms that flash writing/erasing counts for most of
the boot time.
We have also noticed UpdateVariable() (in
MdeModulePkg/Universal/RuntimeDxe/Variable.c) might make 4 accesses to the
same region of Flash to update a non-volatile variable:
// 1. Write variable header
UpdateVariableStore (...,
mVariableModuleGlobal->NonVolatileLastVariableOffset,
sizeof (VARIABLE_HEADER),
(UINT8 *) NextVariable
);
// 2. Set variable state to header valid
NextVariable->State = VAR_HEADER_VALID_ONLY;
UpdateVariableStore (...,
mVariableModuleGlobal->NonVolatileLastVariableOffset + OFFSET_OF
(VARIABLE_HEADER, State),
sizeof (UINT8),
&NextVariable->State
);
// 3. Write variable data
UpdateVariableStore (...,
mVariableModuleGlobal->NonVolatileLastVariableOffset + sizeof
(VARIABLE_HEADER),
(UINT32) VarSize - sizeof (VARIABLE_HEADER),
(UINT8 *) NextVariable + sizeof (VARIABLE_HEADER)
);
// 4. Set variable state to valid
NextVariable->State = VAR_ADDED;
UpdateVariableStore (...,
mVariableModuleGlobal->NonVolatileLastVariableOffset + OFFSET_OF
(VARIABLE_HEADER, State),
sizeof (UINT8),
&NextVariable->State
);
I understand the 4 steps are to prevent the flash to be inconsistent in case
of accidental reset.
Actually the steps 1 and 2 could easily be merged (ie: do
'NextVariable->State = VAR_HEADER_VALID_ONLY' in step 1).
For most variables, it is likely these 4 accesses would be into the same
block of flash. It means this block of flash would be written 4 times.
Could we potentially check if we do a write to the same block of flash and
do a single write?
For instance (untested code):
BlockSize = Fvb->GetBlockSize ();
BlockStart = mVariableModuleGlobal->NonVolatileLastVariableOffset &
~(BlockSize - 1);
BlockEnd = (mVariableModuleGlobal->NonVolatileLastVariableOffset + VarSize)
& ~(BlockSize - 1);
if (BlockStart == BlockEnd) {
NextVariable->State = VAR_ADDED;
UpdateVariableStore (...,
mVariableModuleGlobal->NonVolatileLastVariableOffset,
VarSize,
(UINT8 *) NextVariable
);
} else {
// 1. Write variable header
NextVariable->State = VAR_HEADER_VALID_ONLY;
UpdateVariableStore (...,
mVariableModuleGlobal->NonVolatileLastVariableOffset,
sizeof (VARIABLE_HEADER),
(UINT8 *) NextVariable
);
// 2. Write variable data
UpdateVariableStore (...,
mVariableModuleGlobal->NonVolatileLastVariableOffset + sizeof
(VARIABLE_HEADER),
(UINT32) VarSize - sizeof (VARIABLE_HEADER),
(UINT8 *) NextVariable + sizeof (VARIABLE_HEADER)
);
// 3. Set variable state to valid
NextVariable->State = VAR_ADDED;
UpdateVariableStore (...,
mVariableModuleGlobal->NonVolatileLastVariableOffset + OFFSET_OF
(VARIABLE_HEADER, State),
sizeof (UINT8),
&NextVariable->State
);
}
Regards,
Olivier
------------------------------------------------------------------------------
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and their
applications. Written by three acclaimed leaders in the field,
this first edition is now available. Download your free book today!
http://p.sf.net/sfu/13534_NeoTech
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-devel