-
Notifications
You must be signed in to change notification settings - Fork 279
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
Add an option to truncate the ME file #20
Comments
Great! We tried to reduce the ME image in a very early version of me_cleaner but it didn't work:
This discussion was on a ME image with the FTPR partition intact, I suppose the code that writes stuff in the ROM is in one of the removed Huffman modules (therefore I suppose this won't work on Skylake images, where the modules are intact). Thanks for sharing your discoveries!
|
Cheers for the catch. I would have written a patch by now but I've got no clue about python. I might work on it tomorrow as an exercise to learn it. |
Btw, I'd like not to truncate the image: if the user provides the extracted ME image it can also truncate it with an external tool (like dd), while if it provides a full image it can modify the layout with ifdtool. Either way, there are external tools that already do the job, and I think me_cleaner should just print the minimum allowed size, without modifying the size of the image. |
Oh yeah, at no point was I asking for it to be a default, merely asking that it provides a nice way to see the minimum length. |
Here it is Can you check that the result of your manual inspection of the binary and the output of me_cleaner match? |
Aside from the fact it doesn't match mine (because I'm not doing it properly) it all looks good - I'll try it on my test mule tomorrow (GMT+8) |
I assume this is because it's not aligned properly? (This is straight from my working directory from manually doing it, I've not tried it in a clean folder for this) Edit: No, It looks the same... Edit2: I'm a twit - It looks like at some point I either did the math differently or something silently fixed it - the IFD on the test mule was indeed 0x1000 aligned. Edit3: I'm going to bed - the BIOS is overlapping the ME region, and I assume that is why your tool is baulking on the new rom. I will do this all again tomorrow to double check things. |
OK, I did it completely from scratch, and from what I can tell (I haven't given it 30 minutes yet) everything seems fine (and yes, my IFD regions are fixed now). My working ROM is here: https://nroach44.id.au/upl/coreboot_x220_seabios_20170125.rom Interestingly, if I extract the truncated ME region, me_cleaner will end up making the file bigger. Presumably if I run it on the whole BIOS image it will end up writing into the BIOS region? |
Thanks for your findings! On my T420, I used the 1.5MB ME image found on the coreboot wiki: me_cleaner reported a minimum size of 294912 bytes (0x48000 bytes). So I was able to reduce the image to 294kB. Here is my layout:
Before flashing, unhuffme gave me a [MATCH] for the BUP region. Just passed the 30 minute mark. Now I have a whopping CONFIG_CBFS_SIZE=0x7b5000 for payloads. Might be interesting for squeezing a linux kernel in there. On a side note, I noticed that me_cleaner left over some bytes in the middle. I shaved them off without danger.
|
Awesome! I've added that as an addendum, and when this functionality gets mainstreamed I'll rewrite the blog post. I've just started running my own version of this and it looks like it's all good. |
So far, everything works just fine. You might want to post your blog on the coreboot mailing list - coreboot was originally all about executing linux from flash, people might be happy to hear they can reclaim large portions from the ME for this. |
@alegru me_cleaner has just been included in coreboot, but the integration on the menuconfig has received a negative review. Once we understand if the relocation of the code is possible (see the end) I'll push the updates to coreboot. |
I've finally understood how to relocate the partitions, now the FTPR can be pushed to the beginning of the ME region |
Very nice @corna. What was the problem at the previous ftpr move script? I'll test it at a me8 system later. The parameters are also a great addition. Something that should be there, in my opinion, is a file output. Meaning, not write over the original but expect an input for reading and an output for writing (example: me_cleaner me.bin me_cut.bin) |
@corna Great work! No problems on my T420, just finished waiting 30 minutes. I could reduce the 1.5 ME file to ~74 kB:
This makes my CBFS size 0x7eb000 large. Impressive. I don't think there is much more to gain. |
The previous script didn't correct the bytes 0x0c:0x10 of the LLUT. These bytes aren't documented in me.bios.info, but they are referred in me_unpack.py as "SpiBase: offset of the LUT in the ME region". This field has an absolute offset close to the beginning of the LLUT, but not exactly the same. Anyways, summing it the difference between the new and the old FTPR offset fixed everything.
Doable I've just noted that the minimum size returned by me_cleaner is not reliable, as it returned 4 kB less than the "real" minimum and bricked my X220. Check manually that you're not removing valid data. OT: @platomav do you have write access on me.bios.io? I'd like to fix a couple of things there |
Tested the 5MB image that I extracted from my factory bios. Interestingly, the truncated image (~70 kB) is (marginally) smaller compared to the 1.5MB one after relocation.
CBFS size is 0x7ec000
In both cases I had no problems with this; for testing I deliberately shaved off too much. |
Valid data are cut because the FTPR is set to move at 0x1000 (4KB) and the size reported by me_cleaner at the end relates to FTPR and not the entire ME binary (from $FPT). Apart from that issue, here are some notes:
Note: I'm not mentioning SPS stuff yet. However, in case you missed it, this person tested the script at an SPS 4 (x86 Engine) system.
Igor to the rescue! We would be nowhere without that guy! :)
No, I'm not related to that. I have noticed as well that it has various mistakes or omissions here and there. I've seen some of them corrected at me_unpack and I've added some more at MEA structs. |
Both the Huffman and the LZMA/uncompressed end addresses should be relative to $FPT.
I didn't want to move the FTPR too high because the mysterious value "spibase" (bytes 0x0c:0x10 of the LLUT) points to an address before the start of the FTPR in my image (the relocated FTPR starts at 0x1000 while this address is 0xB40). For now I'm keeping the new FTPR address a bit higher than the real minimum.
The IFD addresses store only the bits 24:12, so they are intrinsically 4 kB aligned.
I'm not sure about this. Probably the extra "unmapped" bytes can be truncated, I'll investigate
Yep, I've missed it! ;)
Indeed :) |
Yes, the -c flag just checks the structure and the signature |
I've just rebuilt and flashed to my test machine - I shrunk the image down to 12000B (me_cleaner advised 11000B, but there was some non-0xFF data at the end there) and the machine doesn't get to the stage where it turns on the back light. I'm not sure if that's a coreboot/SeaBIOS issue but I suspect it may be the ME. |
@nroach44 have you also relocated the FTPR partition? |
Here is what I noticed. That "spibase" always starts before LUT, in weird places. Sometimes at the previous partition and some others within FTPR itself (for example right in between an $MME module). What is always common (GLUT, LLUT, LUT) is that the size between that offset and the start of LUT data (after Chipset/Revision, LUT + 0x40) is always shown inside bytes 2-3 of AddrBase (LUT + 0x9 : LUT + 0x9A). For example, if I take a GLUT partition: Partition = 00 F0 0D 00 (0xDF000) If you subtract SpiBase from LUT_Data, you get 0xDF040 - 0xDE280 = 0xDC0. Check 2nd and 3rd bytes of AddrBase which are C0 0D and thus 0xDC0. |
Edit: @corna I went and re-read the arguments, yes, I just used me_cleaner -r. I can upload the resulting image somewhere if you want. |
@corna Just noting it while I come across it again - it seems that when I run me_cleaner over my me region it makes the file larger:
This had me stumped for a while when trying to re-insert the image. |
Can you run a binary diff between the two? Are you applying |
Neither do I and it especially does not make any sense since that SpiBase offset can sometimes fall into random FTPR data such as an $MME module as I noticed at ME7. Maybe that field is useful for an extra LUT offset verification and nothing else. They could have added the actual LUT offset there instead of a previous offset + a size to calculate. Yes, I cannot understand the reasoning no matter how I look at it. Regardless, based on that finding, there are some things that should be tested:
|
Probably, I'll test it
Probably not, as the relocation didn't work before the adjustment of this field
Probably not, as AddrBase is used during the Huffman decompression and the loading addresses of the modules are signed |
@corna ran me_cleaner -r over a dumped working image, did not adjust layout, same result as before. I will investigate the enlarging issue a bit more and report on that separately. |
I cannot live without them gone... :) Regarding these extra data you mention, maybe you are referring to the ME8+ "uncharted" (not at $FPT) WCOD/LOCL partitions found at 5MB/Corporate SKUs exactly after last $FPT partition. These should be removed as well from such images. Another possible issue is the fact that ME6 does not have a size at the last $FPT entry. But I suppose, in both cases, me_cleaner can just nuke everything after FTPR and call it a day. |
Nope, I'm referring at the extra data remaining in the FTPR Huffman stream |
I've pushed everything to dev: now me_cleaner tries to relocate the data as close as possible to FPT. I've also added a -O option to specify an output file. Untested |
Works! Good job @corna |
Okay, finally got around to re-doing my testing (X220): The truncated image was done simply by moving the region, not actually regenerating the image - the coreboot region hadn't changed. Unless there's some requirement that all the regions be contiguous, the ME didn't like the suggested size. I'll reflash back to a working image and see how far I can cull it down. |
For reference, me_cleaner says "The ME minimum size is 65536 bytes (0x10000 bytes)" which seem roughly correct. The only data cut off is:
|
What do you mean? I'm starting to think that the boot fails if ME can't compute the hash of the subsequent module, which might happen if the image is truncated "too close" to the ending address. Can you try again using the suggested size + 0x1000? |
I usually just shut the machine down and power it on again, but when I flashed the relocated image it wouldn't even finish the EC initialisation - no think light flash. I assume that's because the ME was half booted and didn't like the region being shifted out from underneath it. Edit: that particular issue only applied to the relocation that did end up booting after I pulled the battery. I had flashed an image that I thought would be 0x20000 (double the size), but I missed a zero and bricked it. I'm going to be back home soon and will try it properly. |
ME with 5MB firmware is powered separately from the Host system (M3 power state supported). A global (ME + Host) reset is needed in such case. A simple shutdown only resets the Host, not ME. So, to do a manual global reset, power off the system (not standby), disconnect all power (AC, main battery - RTC battery doesn't matter) and wait for 30 seconds. ME with 1.5MB firmware is not powered separately from the Host system (M3 power state not supported). A system power off is enough in such case to perform a global (ME + Host) reset. |
Right, that explains it. Also this might explain why shrinking the ME region to 0x20000 still doesn't work:
So this whole time ifdtool seems to be wiping the region when I resize it...? When I finish unbricking my X220 I'll flash an image that doesn't have a zeroed ME region... |
Okay, I shrunk the region to
And then truncated the ME file, and then re-inserted it. This still results in a brick. If you wouldn't mind having a squiz at the file here: https://nroach44.id.au/upl/coreboot_x220_seabios_20170204_broken.rom.new Also to double check, the regions can have gaps in them yeah? They don't need to be end-to-end? |
Ah, there is a bug. The SpiBase of LUT is calculated from FD instead of $FPT. In my test, it worked (by accident) because I cleaned a bare Engine region and not a full SPI image, so 0x0 coincided with $FPT offset. |
Hmm, I'm not knowledgeable enough to know if that's behind my issues, but just for completeness' sake, I rebuilt coreboot around the "cleaned, relocated and truncated to 0x20000 length" image. This also meant that the BIOS region was resized to start where the ME region ended. Still results in a brick. I'm going to bed and I'll have a squiz at possibly truncating it to the minimum size before relocation to see if that changes things. |
It is a bug in me_cleaner, nothing to do with your actions. To avoid it, use me_cleaner on your Engine region only (not the whole SPI) and then insert into the SPI to flash back. Or you can wait until it gets fixed. 👍 |
No, I meant that because it works when I don't truncate I don't believe that this is causing my issue. Although I don't remember if the image that I'm working from was cleaned as a rom or just a region. Cheers though! Edit: That said, I'm quite tired (so I might be mis-reading your message) and will check in tomorrow. |
Tried this with latest commits, but still bricked my machine (0x10000 for me) |
Yes, thanks for pointing it out. Fixed in ab4e583 |
Ok, so I've gone through and tested stuff again but with a battery pull after each flash.
It causes the machine to reboot after 30 minutes. I never noticed because I would unbrick the machine, boot it and then flash another image. Running -r on the region as opposed to the whole image doesn't change anything. |
What is the output of |
Just relocated, no truncation yet.
intelmetool -s output is simply:
|
Are you using the very latest version of intelmetool from coreboot? It was recently updated |
Ah, no.
Cleaned and relocated, no truncation:
|
I've just tried on my X220 with a ME7 5MB image (I usually use a ME8 1.5MB dumped from a Chromebook) and it bricked my laptop, I'll work on it |
Yeah, when I have some more time I'll sit down and try and figure out some of the inconsistencies - I'm 99% sure the new "don't work"s from me are with the factory 5MB, but the "works fine" were with the 1.5 from the coreboot wiki. Sorry for the time wasting! |
I've noticed that with my 5 MB image the FTPR is moved up to the minimum possible (0x60) and after changing it to 0x400 (1 kB) it worked. Can you change line 26 to |
Boots fine, unlike every other bad image I didn't need to pull the battery twice (bad images would mean the power light would flash the first time you tried powering it on)
Not been up 30 minutes yet but from the logs it looks like it should be fine. Edit: Passed the 30 minutes mark fine. |
Original request done in 0ac4b4b. |
I've just tested it and logged my findings here https://nroach44.id.au/index.php/2017/01/24/thinkpad-x220-shrink-the-me-region/
Basically if we truncate the ME region to the last byte, update the ifd, everything works as expected.
Would it be possible to have an option to automatically truncate the file if we are cleaning the just the ME region, and if we are doing the whole firmware ROM spit out a ifdtool layout with the smaller ME region?
The text was updated successfully, but these errors were encountered: