Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does not work on Thinkpad T450s #5

Closed
crazyi opened this issue Apr 12, 2020 · 22 comments
Closed

Does not work on Thinkpad T450s #5

crazyi opened this issue Apr 12, 2020 · 22 comments

Comments

@crazyi
Copy link

crazyi commented Apr 12, 2020

I had followed the guide with my T450s, but it didn't work.
I wonder if you can fix the problem?
The attach is the bios and cfg extraction from the bios
Bios.zip
IMG_7399
There is no output when I use setup_var as well as setup_var2 and setup_var_3

@datasone
Copy link
Owner

Where did you extract the Setup section (a.k.a. the PE32Section.bin file)? It seems that the firmware's Setup section is not named after "Setup" so the program didn't find the corresponding section.

@crazyi
Copy link
Author

crazyi commented Apr 12, 2020

Where did you extract the Setup section (a.k.a. the PE32Section.bin file)? It seems that the firmware's Setup section is not named after "Setup" so the program didn't find the corresponding section.

I use the BIOS_Backup_TooKit.EXE to extract the bios rom from my laptop as LENOVO-JBET73WW(1.37).rom.
Then I extract PE32Section.bin with the UEFITool from LENOVO-JBET73WW(1.37).rom as taught by this guide
I also got the original firmware from Lenovo's website, I attched them all here.
bios.zip

@datasone
Copy link
Owner

Well the Setup section of this firmware is named after "PlatformHiiAdvancedDxe" as shown in this pic.
image

This special build only changes the matching name so that it could find the name for setup section in this firmware. You may try if it would work. But as I don't know if there is any different implementation in this firmware and it's pretty easy to brick the PC, USE IT AT YOUR OWN RISK!!!
modGRUBShellSP.zip

@crazyi
Copy link
Author

crazyi commented Apr 13, 2020

@datasone
Thank you for your help. I have tried your special release, but it seems no luck.
IMG_7403

@datasone
Copy link
Owner

Well you could first try to use this build to print out all the variables in the firmware, and you may try to find out where the setup variables reside in.
modGRUBShellPrintVar.zip

After that it is possible to tweak the program to find the corresponding variable and modify the value, but as the variable itself would be selected by guessing, and altering values in the wrong variable will be extremely dangerous, I only recommend to continue while you are capable to unbrick it (which may require removing the CMOS battery to reset BIOS settings or even using the programmer to reflash firmware image).

@crazyi
Copy link
Author

crazyi commented Apr 13, 2020

  1. When I use the latest grub shell, the output of the var names is too much to show in one screen, how can I save this info as this mini shell does not have some basic commands.
  2. As you said, altering values in the wrong variable will be extremely dangerous, I wonder if the programmer CH341A suitable to reflash firmware image?

@datasone
Copy link
Owner

  1. Sorry I forgot it, you could use set pager=1 before setup_var to prevent auto scrolling (just like the UNIX less)
  2. Yes it should be enough, and a programmer backup first is recommended as the rom files from Internet (even the official ones) lacks machine-specific informations such as NIC MAC address.

And this is another build which allows you to specify the variable name and make testing more convenient.

modGRUBShellCustomVarName.zip

Both three setup_var commands are patched and it's usage is setup_var offset [value] [variable name]. e.g. if you want to get the value of the variable cat at offset 0x01, then use setup_var 0x01 read cat.

To preserve compatibility, the third parameter is still the value, here in example I used a word "read" to prevent modify value and it could be any word that is not number to prevent modification. So be careful not to put number here if you only intend to read value.

And if you want to set value then it's very easy to change that "read" to the value, e.g. setup_var 0x02 0x01 cat sets the value of the variable cat at offset 0x02 to 0x01.

@crazyi
Copy link
Author

crazyi commented Apr 14, 2020

  1. I have got the screenshots of the setup_var in output.zip
  2. I also find a guide to remove cfg lock, I followed and got the output like this:

C:\Users\crazyi\Desktop>UEFIPatch.exe $0AJB000.FL1 -o unlock
parseVolume: unknown file system FFF12B8D-7696-4C8B-A985-2747075B4F50
parseVolume: unknown file system 00504624-8A59-4EEB-BD0F-6B36E96128E0
parseFile: non-empty pad-file contents will be destroyed after volume modifications
patch: replaced 10 bytes at offset 1FD6h 75080FBAE80F89442430 -> EB080FBAE80F89442430
Image patched

Is this any help to the issue?

  1. I need another laptop and ch341a to backup and refresh the bios. Those tools lies all in my office but I cannot get there due to the covid-19, I will have a try when I get those tools.
  2. Do you have some technical documents on this bios subject? Following those guides I only know how to do, but I can not know why to do.

@datasone
Copy link
Owner

  1. BiosSetup seems reasonable, but oddly it appeared twice. First test reading known settings value (present in BIOS settings UI) to verify is a good idea.
  2. I'm not familiar with UEFIPatch, but I guess it works like patching the firmware to directly unlock MSR 0xE2 regardless of the BIOS settings, while using the grub tool modifies BIOS settings to unlock it. So those are two different and independent ways.
  3. Actually I'm also not familiar with UEFI things. To be short, the BIOS settings is stored in the NVRAM and thanks to the standard, they can be accessed using UEFI runtime services. In UEFI, many settings, such as boot orders, are stored in variables. The BIOS settings are not particular, so it is also stored in a special variable. The BIOS settings UI works by storing settings in that variable, but many settings was hidden by the OEM. By using this program, you can write to that variable and change the corresponding settings at the offset regardless of if it had been hidden. But for how the offset is determined (i.e. how the IFR extractor works), it is related to UEFI standards and I don't know much about that.
    Those things are all open sourced (UEFITool, UEFIPatch, IFR-Extractor) so if you want to dig deeper, reading source code is a good idea. For this project, all changed code is in setup_var.c.

@crazyi
Copy link
Author

crazyi commented Apr 14, 2020

Thanks for your tips, I am now beginning to understand what you said.
The BIOS setting always stored in the section name BiosSetup, and what I should do is to use your modGRUBShellCustomVarName to read a existing setting which can be checked in the UI settings?
Then locating the real offset for the BIOS setting? In my case, the searching var_name should be CFG lock according to the file extracted by IRFExtractor?
Meanwhile, I got to compile your code on my WSL with ubuntu16.04+gcc4.8.5, but there is always some errors, 1. no make rules for setup_var.c, 2. the automake's version here is 1.15, higher than the required 1.11

cd . && automake-1.15 --gnu
configure.ac:46: error: version mismatch. This is Automake 1.15,
configure.ac:46: but the definition used by this AM_INIT_AUTOMAKE
configure.ac:46: comes from Automake 1.11.6. You should recreate
configure.ac:46: aclocal.m4 with aclocal and run automake again.
configure.ac:46: warning: The 'AM_PROG_MKDIR_P' macro is deprecated, and its use is discouraged.
configure.ac:46: You should use the Autoconf-provided 'AC_PROG_MKDIR_P' macro instead,
configure.ac:46: and use '$(MKDIR_P)' instead of '$(mkdir_p)'in your Makefile.am files.
Makefile:21140: recipe for target 'Makefile.in' failed
make: *** [Makefile.in] Error 1

@datasone
Copy link
Owner

The name BiosSetup is just my guess, there is no way to decide if it is correct, and usually in other firmwares it is named after "Setup" or "Custom".
And for here, the CustomVarName is the UEFI variable name, i.e. the prints of modGrubShellPrintVar (your output.zip). It has nothing to do with the offset.

Here may be some misunderstandings so I'll explain how your problem (or this issue) arised. In normal firmwares, the names of the UEFI variable storing BIOS settings is Setup or Custom. Normally, this program finds variables in such a name and modifies it. And as this UEFI variable stores all the BIOS settings, the program only modifies the value at the required offset to only have the desired settings changed. But in your laptop's firmware, there isn't a variable in such a name, so the program cannot find the BIOS settings variable.
image

And the modGRUBShellCustomVarName provides a way to explicitly set the UEFI variable name, so the program can find variables with the name you put in the parameter. And you should use the guessed UEFI variable name to obtain the BIOS settings variable.

For the compile problems, did you read the Build Notes? I think there shouldn't be explicit calling automake-1.15. As for the "no make rules" problem, it was caused by wrong location of setup_var.c, which has been fixed in 961a33c. The file should be in grub-core/commands/efi directory.

@crazyi
Copy link
Author

crazyi commented Apr 14, 2020

Thank you very much for your explanation, and I am now understanding my situation.
What I am looking for should be a continuous space where it stores the BIOS settings with special UEFI variable name . And 0x7a extracted from IFR extractor is the offset to the initial address of this variable name.
I will have a try once I can get to my office. Thank you again for your help.
P.S. I accidently found this script, I will dig it up to find if it will help to manage the BIOS setting.

@datasone
Copy link
Owner

Yes that's right, and good luck :)

@datasone
Copy link
Owner

Hello, I looked into your PE32Section IFR.txt again this weekend and discovered what variable may be related to the settings.

At the line 1540 (i.e. the "CFG Lock" line), it mentioned that the VarStore is 0x6.
image

The definition of VarStore 0x6 resides in line 33, and its corresponding name is CpuProtocolSetupVar, which is also present in your variable dump screenshots, so it is probably right.
image

But the previous screenshots show wrong name size (all 1024, the "var size" here should be the size of var name) and I'm suspecting this was the reason that this tool won't work. If you test variable names present in the dump and still get no output, then this should be an another problem.

@crazyi
Copy link
Author

crazyi commented May 2, 2020

Hi, @datasone , I'm sorry it took so long to reply as I am busy catching up the working schedule delayed by the lockdown.
In your last comment, you mentioned that the corresponding name should be CpuProtocolSetupVar, then the offset is 0x180db at the beginning of the line 33?
If this is the right command to check with your latest modGRUBShellCustomVarName?
setup_var_3 0x180db read CpuProtocolSetupVar

@datasone
Copy link
Owner

datasone commented May 2, 2020

Well the offset should still be the VarOffset, i.e. 0x7A.

@crazyi
Copy link
Author

crazyi commented May 2, 2020

Seems to be no luck.
11

@datasone
Copy link
Owner

datasone commented May 2, 2020

You may try this build which bypasses the var name size check (as those in your laptop's firmware are all 1024) and see if the variable can be successfully obtained.
modGRUBShellNoCheckVarSize.zip

@crazyi
Copy link
Author

crazyi commented May 2, 2020

I have tested all the output var names using modGRUBShellNoCheckVarSize and it seems still no luck.
11

@datasone
Copy link
Owner

datasone commented May 2, 2020

The only other thing I could think of is that there may be some unprintable character padding in the names. If you'd like to, you can try this which would print out the hex value of the variable name, so it could be confirmed that we are matching the right variable name.
modGRUBShellPrintVarNameHex.zip

@crazyi
Copy link
Author

crazyi commented May 3, 2020

I have checked the ascii of the variable names, and no errors seem to have been found.
But the variable size is wrong definitely.
11
I

@datasone
Copy link
Owner

datasone commented May 3, 2020

Well, I have no idea about what causes the program failed to find the variable for now. The variable size has been ignored and the variable name seems normal. Maybe there are some special implementations in the firmware that prevents normally obtaining the variable (In my memory it was the second Thinkpad generation which uses an UEFI firmware).
So there is temporarily no solution for this issue and I'll leave it here for the moment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants