Thank you so much for your time with such a detailed reply. I need more time to understand all the information :)
On 05/29/2015 10:45 PM, Laszlo Ersek wrote: > On 05/29/15 13:58, Heyi Guo wrote: >> Hi Laszlo and Ard, >> >> As you two are the new maintainers for ArmVirtPkg, I suppose you are the >> right persons to ask this question :) >> >> I'm running UEFI SCT aganst QEMU aarch64, and I got error for functional >> test against HII_CONFIG_ACCESS_PROTOCOL installed in PlatformDxe module. >> >> The test case is BBTestRouteConfigFunctionTestCheckpoint1 in >> TestCase/UEFI/EFI/Protocol/HIIConfigAccess/BlackBoxTest/HIIConfigAccessBBTestFunction.c; >> it will construct the configuration in some way (sorry I'm not familiar >> with HII and not understand the process clearly), and then call >> RouteConfig of HII_CONFIG_ACCESS_PROTOCOL. > Well, "some way" is certainly the key question here. > >> The configuration constructed is like this: > I'm breaking it up: > >> GUID=1cc53572800cab4c87ac3b084a6304b1& >> NAME=004d00610069006e0046006f0072006d00530074006100740065& >> PATH=01041400dfc5dcd907405e4390988970935504b27fff0400& >> OFFSET=0000& >> WIDTH=0020& >> VALUE=00000000000000000000000000000000000000000000007400650073006e0055 > Okay, it's been a very long time since I've last looked at HII config > strings. In any case, if you play with PlatformDxe (go to Device Manager > | OVMF Platform Configuration, play with the preferred resolution), > *and* you have build OVMF / ArmVirtPkg with sufficiently long debug > messages enabled, then you will see debug messages like: > > ExtractConfig: Request="GUID=1cc53572800cab4c87ac3b084a6304b1& > NAME=004d00610069006e0046006f0072006d00530074006100740065& > PATH=01041400dfc5dcd907405e4390988970935504b27fff0400& > OFFSET=0& > WIDTH=0024" > > ExtractConfig: Results="GUID=1cc53572800cab4c87ac3b084a6304b1& > NAME=004d00610069006e0046006f0072006d00530074006100740065& > PATH=01041400dfc5dcd907405e4390988970935504b27fff0400& > OFFSET=0& > WIDTH=0024&VALUE=000000000000000000000000000000000000000000000030003800340078003000340036" > > The GUID that you can see is gOvmfPlatformConfigGuid, and it is used in > "OvmfPkg/PlatformDxe/Platform.c" as the formset GUID. So basically the > GUID just identifies the formset for which the HII message is for. > > The NAME entry is hexadecimal encoding for the CHAR16 string > "MainFormState". "MainFormState" is the name of the object that stores > the state of the form / widget in binary representation. The type is > MAIN_FORM_STATE, declared in "OvmfPkg/PlatformDxe/Platform.h". The form > definition in "OvmfPkg/PlatformDxe/PlatformForms.vfr" defines the object > with name "MainFormState", with type MAIN_FORM_STATE, as the state of > the form. > > (You can see some -- hopefully -- enlightening messages in the commit log: > > git log -- OvmfPkg/PlatformDxe/ | less > ) > > I'm unsure about PATH, it probably partakes in identifying the form > within the formset, or some such. > > In any case, OFFSET, WIDTH, and VALUE describe the contents of > MainFormState, in binary representation (well, a subset thereof). You > can see in "OvmfPkg/PlatformDxe/Platform.h" that the size of > MAIN_FORM_STATE is (2 * 16 + 4) == 30 == 0x24. That means that the above > OFFSET, WIDTH and VALUE fields define the complete contents of > MAIN_FORM_STATE. > > // > // This structure describes the form state. Its fields relate strictly > // to the visual widgets on the form. > // > typedef struct { > UINT16 CurrentPreferredResolution[MAXSIZE_RES_CUR]; > UINT32 NextPreferredResolution; > } MAIN_FORM_STATE; > > The "CurrentPreferredResolution" field is a CHAR16 string; it > corresponds to the (read only) text field that you see on the form to > the right of the "Preferred Resolution at Next Boot" label. Its maximum > size is MAXSIZE_RES_CUR==16 UCS2 characters, including the terminating > L'\0'. > > The "NextPreferredResolution" field is an index into the dynamically > gathered list of resolutions that the firstly registered GOP supports. > You can see this selection to the right of the "Change Preferred > Resolution for Next Boot" label. > > (These two fields are separate on the form because > CurrentPreferredResolution is parsed from non-volatile variable data: it > can be unset to begin with, plus it can be a resolution that is not even > *found* in the GOP's list. This might happen eg. if you change the model > of the emulated video card, or change its video RAM size. Whereas the > drop-down list offers the currently available GOP modes. So you pick > your preferred resolution, select "Commit Changes and Exit", and > (ultimately) reboot the VM.) > > Above I quoted the ExtractConfig messages; such messages relate to the > form engine / display browser extracting configuration from drivers, so > that the form state can be updated for display. (Refer to SVN r15374.) > > The other direction is called "RouteConfig" (see SVN r15375), when the > form engine updates *part* of the form state (thereby updating part of > the preexistent driver configuration). This is triggered when you hit > Enter on "Commit Changes and Exit" (see how the QUESTION_SAVE_EXIT entry > is hooked up to EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT, in the VFR > file and in Callback()) *and* the state actually changed. > > For example, if you change the NextPreferredResolution dropdown list > index from 0 to 1, the form engine will send down the following config > string: > > > RouteConfig: Configuration="GUID=1cc53572800cab4c87ac3b084a6304b1& > NAME=004d00610069006e0046006f0072006d00530074006100740065& > PATH=01041400dfc5dcd907405e4390988970935504b27fff0400& > > (the usual stuff) > > OFFSET=0000& > WIDTH=0020&VALUE=0000000000000000000000000000000000000030003800340078003000340036&OFFSET=0020& > WIDTH=0004& > VALUE=00000001" > > Aha! So it sends the first 32 bytes (the CurrentPreferredResolution UCS2 > string) first, then the value of the UINT32 NextPreferredResolution > index second. > > Our RouteConfig() handler performs a read-modify-write cycle in response > -- that's necessary because the config update can be partial in general. > See again r15375. > > Alright, now we understand what's what. > > Apparently, the test case is trying to send down the following config > string: > >> OFFSET=0000& >> WIDTH=0020& >> VALUE=00000000000000000000000000000000000000000000007400650073006e0055 > wich means > > set the 'CurrentPreferredResolution' string of the form state to > '<bunch of zeroes>tesnU' > > Obviously, our RouteConfig() handler ignores any "changes" to this > string -- the string is marked READ_ONLY on the form to begin with, it > only serves display purposes. So we have: > > RouteConfig() > // READ > PlatformConfigToFormState() > PlatformConfigLoad() > GetVariable2() > gRT->GetVariable() > > // MODIFY (may be partial) > gHiiConfigRouting->ConfigToBlock() > > // WRITE > FormStateToPlatformConfig() > PlatformConfigSave() > gRT->SetVariable() > >> I traced the code and found it failed in FormStateToPlatformConfig in >> Platform.c, due to mNumGopModes being 0. >> >> if (MainFormState->NextPreferredResolution >= mNumGopModes) { >> return EFI_INVALID_PARAMETER; >> } > Yes. Near the end of this RMW cycle, the NextPreferredResolution field > is 0. That's because no GOP has been installed yet, so the READ part -- > regardless of the existence of the non-volatile variable that stores the > preferred resolution -- leaves NextPreferredResolution at zero. After > all there is no list of resolutions to search, and determine the index > of the current preference. > > In addition, in the MODIFY part, the config string that the tester app > sends down doesn't cover NextPreferredResolution at all (that would be > OFFSET=0020, WIDTH=0004). > > This is not a problem per se. For example, if the non-volatile variable > states 2048*2048 as your current (last) preference, but your new video > ram setting (from the QEMU side) only allows a max resolution of > 1024x768 (just making up the numbers now), there's no way 2048*2048 will > be found in the list. In this case, the list index will be left at zero, > as initial choice. > > Now, since we're *routing* the config, that means the user has actually > selected "Commit". In this case the resolution at index zero (which is > usually 640x480) will be looked up from the list of resolutions that the > GOP advertised, and written to the non-volatile variable. > > However: > >> I suppose GOP related data will be initialized when >> gEfiGraphicsOutputProtocolGuid is installed, > Yes. Routing *any* config (ie. committing any selection made on the > form) makes no sense if the resolution list is empty. You cannot select > an element in that empty list at any subscript. You cannot derive the > preferred next resolution, and you cannot write it to the non-volatile > variable. > > This is why FormStateToPlatformConfig() returns EFI_INVALID_PARAMETER: > the form state is untranslateable to platform configuration. > > In normal operation, this can never happen, because using the form, you > can never trigger a RouteConfig unless at least one resolution has been > collected. > > Basically, the tester utility is sending a RouteConfig message with > invalid, nonsensical configuration. It says "leave > NextPreferredResolution at its current value, *and* make that > configuration permanent". Well, the configuration corresponding to the > current value of NextPreferredResolution *cannot* be made permanent, > because it makes no sense. It's an index into something that has not > been initialized yet. > >> so the questions are: >> >> 1. Shall I enable vga on qemu to pass this test? > Yes. > >> How to enable vga? I >> tried -display sdl -vga std, but nothing changed. > Build ArmVirtQemu with -D INTEL_BDS, and then pass the following options > to QEMU: > > -M virt -cpu cortex-a57 -display sdl -device VGA > >> 2. Can we modify the code to make it not depend on GOP? > No. > > I don't know how the tester utility composes the config string, but it > can't just send down (a seemingly random) one, and expect the driver to > bend over backwards and make it permanent. > > We could probably hack it around, by postponing the installation of the > EFI_HII_CONFIG_ACCESS_PROTOCOL instance from the entry point of the > driver (PlatformInit()) to the GOP installation callback > (GopInstalled()). This would simply prevent the tester utility from > finding the RouteConfig() function, because until after GOP installation > PlatformDxe would simply not expose itself as HII-accessible. > > However, until someone provides evidence that OvmfPkg/PlatformDxe/, > as-is, breaks an HII rule, I'm not willing to write such a patch. I'll > have to be shown why the tester utility is in its right to do what it > does, and why PlatformDxe is wrong to reject it. > >> Please kindly help with this issue and correct me if there is anything >> wrong in my understanding. > I hope the above helps. > > Thanks > Laszlo > ------------------------------------------------------------------------------ _______________________________________________ edk2-devel mailing list edk2-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/edk2-devel