From 8ff050d3893f0115b8bd3f1feda5d032f89fbc32 Mon Sep 17 00:00:00 2001 From: Francis Rowe Date: Wed, 24 Dec 2014 00:33:45 +0000 Subject: ich9deblob: Replace makefile (use dependencies) Use .h and .c files properly. Use header guards. Define function names in .h files (actual functions in the .c files), and so on. Move all functions from the .h files to corresponding .c files. --- resources/utilities/ich9deblob/Makefile | 22 +- .../utilities/ich9deblob/descriptor/descriptor.c | 128 +++++++++++ .../utilities/ich9deblob/descriptor/descriptor.h | 111 +-------- resources/utilities/ich9deblob/gbe/gbe.c | 107 +++++++++ resources/utilities/ich9deblob/gbe/gbe.h | 81 +------ resources/utilities/ich9deblob/ich9deblob.c | 248 --------------------- resources/utilities/ich9deblob/main.c | 248 +++++++++++++++++++++ resources/utilities/ich9deblob/x86compatibility.c | 3 +- resources/utilities/ich9deblob/x86compatibility.h | 33 +++ 9 files changed, 550 insertions(+), 431 deletions(-) create mode 100644 resources/utilities/ich9deblob/descriptor/descriptor.c create mode 100644 resources/utilities/ich9deblob/gbe/gbe.c delete mode 100644 resources/utilities/ich9deblob/ich9deblob.c create mode 100644 resources/utilities/ich9deblob/main.c create mode 100644 resources/utilities/ich9deblob/x86compatibility.h (limited to 'resources') diff --git a/resources/utilities/ich9deblob/Makefile b/resources/utilities/ich9deblob/Makefile index 0a69882a..36a892ce 100644 --- a/resources/utilities/ich9deblob/Makefile +++ b/resources/utilities/ich9deblob/Makefile @@ -18,10 +18,24 @@ # CC=gcc -CFLAGS=-I. +CFLAGS=-I. -Wall -g -ich9deblob: ich9deblob.c descriptor/descriptor.h gbe/gbe.h - $(CC) $(CFLAGS) ich9deblob.c descriptor/descriptor.h gbe/gbe.h -o ich9deblob +all: ich9deblob + +ich9deblob: main.o descriptor/descriptor.o gbe/gbe.o x86compatibility.o + $(CC) $(CFLAGS) main.o descriptor/descriptor.o gbe/gbe.o x86compatibility.o -o ich9deblob + +main.o: main.c + $(CC) $(CFLAGS) -c main.c -o main.o + +descriptor/descriptor.o: descriptor/descriptor.c + $(CC) $(CFLAGS) -c descriptor/descriptor.c -o descriptor/descriptor.o + +gbe/gbe.o: gbe/gbe.c + $(CC) $(CFLAGS) -c gbe/gbe.c -o gbe/gbe.o + +x86compatibility.o: x86compatibility.c + $(CC) $(CFLAGS) -c x86compatibility.c -o x86compatibility.o clean: - rm -f ich9deblob *.o + rm -f ich9deblob *.o */*.o diff --git a/resources/utilities/ich9deblob/descriptor/descriptor.c b/resources/utilities/ich9deblob/descriptor/descriptor.c new file mode 100644 index 00000000..0e7f2bf7 --- /dev/null +++ b/resources/utilities/ich9deblob/descriptor/descriptor.c @@ -0,0 +1,128 @@ +/* + * descriptor/descriptor.c + * This file is part of the ich9deblob utility from the libreboot project + * + * Copyright (C) 2014 Steve Shenton + * Francis Rowe + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * Provide descriptor related functions. + */ + +#include +#include + +/* structs describing the data in descriptor region */ +#include "descriptor.h" + +/* + * --------------------------------------------------------------------- + * Descriptor functions + * --------------------------------------------------------------------- + */ + +/* + * Modify the flash descriptor, to remove the ME/AMT, and disable all other regions + * Only Flash Descriptor, Gbe and BIOS regions (BIOS region fills factoryRomSize-12k) are left. + * Tested on ThinkPad X200 and X200S. X200T and other GM45 targets may also work. + * Also described in docs/hcl/x200_remove_me.html + */ +struct DESCRIPTORREGIONRECORD deblobbedDescriptorStructFromFactory(struct DESCRIPTORREGIONRECORD factoryDescriptorStruct, unsigned int factoryRomSize) +{ + struct DESCRIPTORREGIONRECORD deblobbedDescriptorStruct; + memcpy(&deblobbedDescriptorStruct, &factoryDescriptorStruct, DESCRIPTORREGIONSIZE); + + /* + * set number of regions from 4 -> 2 (0 based, so 4 means 5 and 2 + * means 3. We want 3 regions: descriptor, gbe and bios, in that order) + */ + deblobbedDescriptorStruct.flMaps.flMap0.NR = 2; + + /* + * make descriptor writable from OS. This is that the user can run: + * sudo ./flashrom -p internal:laptop=force_I_want_a_brick + * from the OS, without relying an an external SPI flasher, while + * being able to write to the descriptor region (locked by default, + * until making the change below): + */ + deblobbedDescriptorStruct.masterAccessSection.flMstr1.fdRegionWriteAccess = 1; + + /* relocate BIOS region and increase size to fill image */ + deblobbedDescriptorStruct.regionSection.flReg1.BASE = 3; // 3<> FLREGIONBITSHIFT) - 1); + /* + * ^ for example, 8MB ROM, that's 8388608 bytes. + * ^ 8388608>>FLREGIONBITSHIFT (or 8388608/4096) = 2048 bytes + * 2048 - 1 = 2047 bytes. + * This defines where the final 0x1000 (4KiB) page starts in the flash chip, because the hardware does: + * 2047<>FLREGIONBITSHIFT) is well outside the higher 8MB range. + */ + + /* relocate Gbe region to begin at 4KiB (immediately after the flash descriptor) */ + deblobbedDescriptorStruct.regionSection.flReg3.BASE = 1; // 1<>FLREGIONBITSHIFT) is well outside the higher 8MB range. + */ + + /* disable ME in ICHSTRAP0 - the ME is a blob, we don't want it in libreboot */ + deblobbedDescriptorStruct.ichStraps.ichStrap0.meDisable = 1; + + /* disable ME and TPM in MCHSTRAP0 */ + deblobbedDescriptorStruct.mchStraps.mchStrap0.meDisable = 1; // ME is a blob. not wanted in libreboot. + deblobbedDescriptorStruct.mchStraps.mchStrap0.tpmDisable = 1; // not wanted in libreboot + + /* + * disable ME, apart from chipset bugfixes (ME region should first be re-enabled above) + * This is sort of like the CPU microcode updates, but for the chipset + * (commented out below here, since blobs go against libreboot's purpose, + * but may be interesting for others) + * deblobbedDescriptorStruct.mchStraps.mchStrap0.meAlternateDisable = 1; + */ + + /* debugging */ + printf("\nOriginal (factory.rom) Descriptor start block: %08x ; Descriptor end block: %08x\n", factoryDescriptorStruct.regionSection.flReg0.BASE << FLREGIONBITSHIFT, factoryDescriptorStruct.regionSection.flReg0.LIMIT << FLREGIONBITSHIFT); + printf("Original (factory.rom) BIOS start block: %08x ; BIOS end block: %08x\n", factoryDescriptorStruct.regionSection.flReg1.BASE << FLREGIONBITSHIFT, factoryDescriptorStruct.regionSection.flReg1.LIMIT << FLREGIONBITSHIFT); + printf("Original (factory.rom) ME start block: %08x ; ME end block: %08x\n", factoryDescriptorStruct.regionSection.flReg2.BASE << FLREGIONBITSHIFT, factoryDescriptorStruct.regionSection.flReg2.LIMIT << FLREGIONBITSHIFT); + printf("Original (factory.rom) GBe start block: %08x ; GBe end block: %08x\n", factoryDescriptorStruct.regionSection.flReg3.BASE << FLREGIONBITSHIFT, factoryDescriptorStruct.regionSection.flReg3.LIMIT << FLREGIONBITSHIFT); + + printf("\nRelocated (libreboot.rom) Descriptor start block: %08x ; Descriptor end block: %08x\n", deblobbedDescriptorStruct.regionSection.flReg0.BASE << FLREGIONBITSHIFT, deblobbedDescriptorStruct.regionSection.flReg0.LIMIT << FLREGIONBITSHIFT); + printf("Relocated (libreboot.rom) BIOS start block: %08x ; BIOS end block: %08x\n", deblobbedDescriptorStruct.regionSection.flReg1.BASE << FLREGIONBITSHIFT, deblobbedDescriptorStruct.regionSection.flReg1.LIMIT << FLREGIONBITSHIFT); + printf("Relocated (libreboot.rom) ME start block: %08x ; ME end block: %08x\n", deblobbedDescriptorStruct.regionSection.flReg2.BASE << FLREGIONBITSHIFT, deblobbedDescriptorStruct.regionSection.flReg2.LIMIT << FLREGIONBITSHIFT); + printf("Relocated (libreboot.rom) GBe start block: %08x ; GBe end block: %08x\n", deblobbedDescriptorStruct.regionSection.flReg3.BASE << FLREGIONBITSHIFT, deblobbedDescriptorStruct.regionSection.flReg3.LIMIT << FLREGIONBITSHIFT); + + return deblobbedDescriptorStruct; +} diff --git a/resources/utilities/ich9deblob/descriptor/descriptor.h b/resources/utilities/ich9deblob/descriptor/descriptor.h index 847daee8..a3dd340b 100644 --- a/resources/utilities/ich9deblob/descriptor/descriptor.h +++ b/resources/utilities/ich9deblob/descriptor/descriptor.h @@ -31,9 +31,6 @@ #ifndef DESCRIPTORSTRUCT_H #define DESCRIPTORSTRUCT_H -#include -#include - /* size of the descriptor in bytes */ #define DESCRIPTORREGIONSIZE 0x1000 @@ -45,6 +42,12 @@ */ #define FLREGIONBITSHIFT 0xC +/* + * --------------------------------------------------------------------- + * Descriptor struct representing the data + * --------------------------------------------------------------------- + */ + struct FLVALSIG { unsigned int signature; @@ -75,12 +78,6 @@ struct FLMAP0 */ }; -/* - * --------------------------------------------------------------------- - * Descriptor struct representing the data - * --------------------------------------------------------------------- - */ - struct FLMAP1 { unsigned char FMBA : 8; @@ -255,100 +252,10 @@ struct DESCRIPTORREGIONRECORD { /* * --------------------------------------------------------------------- - * Descriptor functions + * Function declarations (keep gcc/make happy. check them in descriptor.c) * --------------------------------------------------------------------- */ - -/* - * Modify the flash descriptor, to remove the ME/AMT, and disable all other regions - * Only Flash Descriptor, Gbe and BIOS regions (BIOS region fills factoryRomSize-12k) are left. - * Tested on ThinkPad X200 and X200S. X200T and other GM45 targets may also work. - * Also described in docs/hcl/x200_remove_me.html - */ -struct DESCRIPTORREGIONRECORD deblobbedDescriptorStructFromFactory(struct DESCRIPTORREGIONRECORD factoryDescriptorStruct, unsigned int factoryRomSize) -{ - struct DESCRIPTORREGIONRECORD deblobbedDescriptorStruct; - memcpy(&deblobbedDescriptorStruct, &factoryDescriptorStruct, DESCRIPTORREGIONSIZE); - - /* - * set number of regions from 4 -> 2 (0 based, so 4 means 5 and 2 - * means 3. We want 3 regions: descriptor, gbe and bios, in that order) - */ - deblobbedDescriptorStruct.flMaps.flMap0.NR = 2; - - /* - * make descriptor writable from OS. This is that the user can run: - * sudo ./flashrom -p internal:laptop=force_I_want_a_brick - * from the OS, without relying an an external SPI flasher, while - * being able to write to the descriptor region (locked by default, - * until making the change below): - */ - deblobbedDescriptorStruct.masterAccessSection.flMstr1.fdRegionWriteAccess = 1; - - /* relocate BIOS region and increase size to fill image */ - deblobbedDescriptorStruct.regionSection.flReg1.BASE = 3; // 3<> FLREGIONBITSHIFT) - 1); - /* - * ^ for example, 8MB ROM, that's 8388608 bytes. - * ^ 8388608>>FLREGIONBITSHIFT (or 8388608/4096) = 2048 bytes - * 2048 - 1 = 2047 bytes. - * This defines where the final 0x1000 (4KiB) page starts in the flash chip, because the hardware does: - * 2047<>FLREGIONBITSHIFT) is well outside the higher 8MB range. - */ - - /* relocate Gbe region to begin at 4KiB (immediately after the flash descriptor) */ - deblobbedDescriptorStruct.regionSection.flReg3.BASE = 1; // 1<>FLREGIONBITSHIFT) is well outside the higher 8MB range. - */ - - /* disable ME in ICHSTRAP0 - the ME is a blob, we don't want it in libreboot */ - deblobbedDescriptorStruct.ichStraps.ichStrap0.meDisable = 1; - - /* disable ME and TPM in MCHSTRAP0 */ - deblobbedDescriptorStruct.mchStraps.mchStrap0.meDisable = 1; // ME is a blob. not wanted in libreboot. - deblobbedDescriptorStruct.mchStraps.mchStrap0.tpmDisable = 1; // not wanted in libreboot - - /* - * disable ME, apart from chipset bugfixes (ME region should first be re-enabled above) - * This is sort of like the CPU microcode updates, but for the chipset - * (commented out below here, since blobs go against libreboot's purpose, - * but may be interesting for others) - * deblobbedDescriptorStruct.mchStraps.mchStrap0.meAlternateDisable = 1; - */ - - /* debugging */ - printf("\nOriginal (factory.rom) Descriptor start block: %08x ; Descriptor end block: %08x\n", factoryDescriptorStruct.regionSection.flReg0.BASE << FLREGIONBITSHIFT, factoryDescriptorStruct.regionSection.flReg0.LIMIT << FLREGIONBITSHIFT); - printf("Original (factory.rom) BIOS start block: %08x ; BIOS end block: %08x\n", factoryDescriptorStruct.regionSection.flReg1.BASE << FLREGIONBITSHIFT, factoryDescriptorStruct.regionSection.flReg1.LIMIT << FLREGIONBITSHIFT); - printf("Original (factory.rom) ME start block: %08x ; ME end block: %08x\n", factoryDescriptorStruct.regionSection.flReg2.BASE << FLREGIONBITSHIFT, factoryDescriptorStruct.regionSection.flReg2.LIMIT << FLREGIONBITSHIFT); - printf("Original (factory.rom) GBe start block: %08x ; GBe end block: %08x\n", factoryDescriptorStruct.regionSection.flReg3.BASE << FLREGIONBITSHIFT, factoryDescriptorStruct.regionSection.flReg3.LIMIT << FLREGIONBITSHIFT); - - printf("\nRelocated (libreboot.rom) Descriptor start block: %08x ; Descriptor end block: %08x\n", deblobbedDescriptorStruct.regionSection.flReg0.BASE << FLREGIONBITSHIFT, deblobbedDescriptorStruct.regionSection.flReg0.LIMIT << FLREGIONBITSHIFT); - printf("Relocated (libreboot.rom) BIOS start block: %08x ; BIOS end block: %08x\n", deblobbedDescriptorStruct.regionSection.flReg1.BASE << FLREGIONBITSHIFT, deblobbedDescriptorStruct.regionSection.flReg1.LIMIT << FLREGIONBITSHIFT); - printf("Relocated (libreboot.rom) ME start block: %08x ; ME end block: %08x\n", deblobbedDescriptorStruct.regionSection.flReg2.BASE << FLREGIONBITSHIFT, deblobbedDescriptorStruct.regionSection.flReg2.LIMIT << FLREGIONBITSHIFT); - printf("Relocated (libreboot.rom) GBe start block: %08x ; GBe end block: %08x\n", deblobbedDescriptorStruct.regionSection.flReg3.BASE << FLREGIONBITSHIFT, deblobbedDescriptorStruct.regionSection.flReg3.LIMIT << FLREGIONBITSHIFT); - - return deblobbedDescriptorStruct; -} + +struct DESCRIPTORREGIONRECORD deblobbedDescriptorStructFromFactory(struct DESCRIPTORREGIONRECORD factoryDescriptorStruct, unsigned int factoryRomSize); #endif diff --git a/resources/utilities/ich9deblob/gbe/gbe.c b/resources/utilities/ich9deblob/gbe/gbe.c new file mode 100644 index 00000000..b1c55dd9 --- /dev/null +++ b/resources/utilities/ich9deblob/gbe/gbe.c @@ -0,0 +1,107 @@ +/* + * gbe/gbe.c + * This file is part of the ich9deblob utility from the libreboot project + * + * Copyright (C) 2014 Steve Shenton + * Francis Rowe + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * Provide gbe related functions. + */ + +#include +#include + +/* structs describing the data from gbe region */ +#include "gbe.h" + +/* + * --------------------------------------------------------------------- + * Gbe functions: + * --------------------------------------------------------------------- + */ + +/* Read a 16-bit unsigned int from a supplied region buffer */ +unsigned short gbeGetRegionWordFrom8kBuffer(int index, char* regionData) +{ + return *((unsigned short*)(regionData + (index * 2))); +} + +/* + * checksum calculation for 8k gbe region (algorithm based on datasheet) + * also works for 4k buffers, so long as isBackup remains false + */ +unsigned short gbeGetChecksumFrom8kBuffer(char* regionData, unsigned short desiredValue, char isBackup) +{ + int i; + + unsigned short regionWord; /* store words here for adding to checksum */ + unsigned short checksum = 0; /* this gbe's checksum */ + unsigned short offset = 0; /* in bytes, from the start of the gbe region. */ + + /* + * if isBackup is true, use 2nd gbe region ("backup" region) + * this function uses *word* not *byte* indexes, hence the bit shift. + */ + if (isBackup) offset = GBEREGIONSIZE_4K>>1; + + for (i = 0; i < 0x3F; i++) { + regionWord = gbeGetRegionWordFrom8kBuffer(i+offset, regionData); + checksum += regionWord; + } + checksum = desiredValue - checksum; + return checksum; +} + +/* checksum calculation for 4k gbe struct (algorithm based on datasheet) */ +unsigned short gbeGetChecksumFrom4kStruct(struct GBEREGIONRECORD_4K gbeStruct4k, unsigned short desiredValue) +{ + char gbeBuffer4k[GBEREGIONSIZE_4K]; + memcpy(&gbeBuffer4k, &gbeStruct4k, GBEREGIONSIZE_4K); + return gbeGetChecksumFrom8kBuffer(gbeBuffer4k, desiredValue, 0); +} + +/* modify the gbe region extracted from a factory.rom dump */ +struct GBEREGIONRECORD_8K deblobbedGbeStructFromFactory(struct GBEREGIONRECORD_8K factoryGbeStruct8k) +{ + /* + * Correct the main gbe region. By default, the X200 (as shipped from Lenovo) comes + * with a broken main gbe region, where the backup gbe region is used instead. Modify + * it so that the main region is usable. + */ + + struct GBEREGIONRECORD_8K deblobbedGbeStruct8k; + memcpy(&deblobbedGbeStruct8k, &factoryGbeStruct8k, GBEREGIONSIZE_8K); + + deblobbedGbeStruct8k.backup.checkSum = gbeGetChecksumFrom4kStruct(deblobbedGbeStruct8k.backup, 0xBABA); + memcpy(&deblobbedGbeStruct8k.main, &deblobbedGbeStruct8k.backup, GBEREGIONSIZE_4K); + + /* + * Debugging: + * calculate the 0x3F'th 16-bit uint to make the desired final checksum for GBe + * observed checksum matches (from X200 factory.rom dumps) on main: 0x3ABA 0x34BA 0x40BA. spec defined as 0xBABA. + * X200 ships with a broken main gbe region by default (invalid checksum, and more) + * The "backup" gbe regions on these machines are correct, though, and is what the machines default to + * For libreboot's purpose, we can do much better than that by fixing the main one... below is only debugging + */ + printf("\nfactory Gbe (main): calculated Gbe checksum: 0x%hx and actual GBe checksum: 0x%hx\n", gbeGetChecksumFrom4kStruct(factoryGbeStruct8k.main, 0xBABA), factoryGbeStruct8k.main.checkSum); + printf("factory Gbe (backup) calculated Gbe checksum: 0x%hx and actual GBe checksum: 0x%hx\n", gbeGetChecksumFrom4kStruct(factoryGbeStruct8k.backup, 0xBABA), factoryGbeStruct8k.backup.checkSum); + printf("\ndeblobbed Gbe (main): calculated Gbe checksum: 0x%hx and actual GBe checksum: 0x%hx\n", gbeGetChecksumFrom4kStruct(deblobbedGbeStruct8k.main, 0xBABA), deblobbedGbeStruct8k.main.checkSum); + printf("deblobbed Gbe (backup) calculated Gbe checksum: 0x%hx and actual GBe checksum: 0x%hx\n", gbeGetChecksumFrom4kStruct(deblobbedGbeStruct8k.backup, 0xBABA), deblobbedGbeStruct8k.backup.checkSum); + + return deblobbedGbeStruct8k; +} diff --git a/resources/utilities/ich9deblob/gbe/gbe.h b/resources/utilities/ich9deblob/gbe/gbe.h index 0e3f0595..9647d806 100644 --- a/resources/utilities/ich9deblob/gbe/gbe.h +++ b/resources/utilities/ich9deblob/gbe/gbe.h @@ -33,9 +33,6 @@ #ifndef GBESTRUCT_H #define GBESTRUCT_H -#include -#include - /* Size of the full gbe region in bytes */ #define GBEREGIONSIZE_8K 0x2000 /* @@ -80,79 +77,13 @@ struct GBEREGIONRECORD_8K { /* * --------------------------------------------------------------------- - * Gbe functions: + * Function declarations (keep gcc/make happy. check them in gbe.c) * --------------------------------------------------------------------- */ - -/* Read a 16-bit unsigned int from a supplied region buffer */ -unsigned short gbeGetRegionWordFrom8kBuffer(int index, char* regionData) -{ - return *((unsigned short*)(regionData + (index * 2))); -} - -/* - * checksum calculation for 8k gbe region (algorithm based on datasheet) - * also works for 4k buffers, so long as isBackup remains false - */ -unsigned short gbeGetChecksumFrom8kBuffer(char* regionData, unsigned short desiredValue, char isBackup) -{ - int i; - - unsigned short regionWord; /* store words here for adding to checksum */ - unsigned short checksum = 0; /* this gbe's checksum */ - unsigned short offset = 0; /* in bytes, from the start of the gbe region. */ - - /* - * if isBackup is true, use 2nd gbe region ("backup" region) - * this function uses *word* not *byte* indexes, hence the bit shift. - */ - if (isBackup) offset = GBEREGIONSIZE_4K>>1; - - for (i = 0; i < 0x3F; i++) { - regionWord = gbeGetRegionWordFrom8kBuffer(i+offset, regionData); - checksum += regionWord; - } - checksum = desiredValue - checksum; - return checksum; -} - -/* checksum calculation for 4k gbe struct (algorithm based on datasheet) */ -unsigned short gbeGetChecksumFrom4kStruct(struct GBEREGIONRECORD_4K gbeStruct4k, unsigned short desiredValue) -{ - char gbeBuffer4k[GBEREGIONSIZE_4K]; - memcpy(&gbeBuffer4k, &gbeStruct4k, GBEREGIONSIZE_4K); - return gbeGetChecksumFrom8kBuffer(gbeBuffer4k, desiredValue, 0); -} - -/* modify the gbe region extracted from a factory.rom dump */ -struct GBEREGIONRECORD_8K deblobbedGbeStructFromFactory(struct GBEREGIONRECORD_8K factoryGbeStruct8k) -{ - /* - * Correct the main gbe region. By default, the X200 (as shipped from Lenovo) comes - * with a broken main gbe region, where the backup gbe region is used instead. Modify - * it so that the main region is usable. - */ - - struct GBEREGIONRECORD_8K deblobbedGbeStruct8k; - memcpy(&deblobbedGbeStruct8k, &factoryGbeStruct8k, GBEREGIONSIZE_8K); - - deblobbedGbeStruct8k.backup.checkSum = gbeGetChecksumFrom4kStruct(deblobbedGbeStruct8k.backup, 0xBABA); - memcpy(&deblobbedGbeStruct8k.main, &deblobbedGbeStruct8k.backup, GBEREGIONSIZE_4K); - - /* - * Debugging: - * calculate the 0x3F'th 16-bit uint to make the desired final checksum for GBe - * observed checksum matches (from X200 factory.rom dumps) on main: 0x3ABA 0x34BA 0x40BA. spec defined as 0xBABA. - * X200 ships with a broken main gbe region by default (invalid checksum, and more) - * The "backup" gbe regions on these machines are correct, though, and is what the machines default to - * For libreboot's purpose, we can do much better than that by fixing the main one... below is only debugging - */ - printf("\nfactory Gbe (main): calculated Gbe checksum: 0x%hx and actual GBe checksum: 0x%hx\n", gbeGetChecksumFrom4kStruct(factoryGbeStruct8k.main, 0xBABA), factoryGbeStruct8k.main.checkSum); - printf("factory Gbe (backup) calculated Gbe checksum: 0x%hx and actual GBe checksum: 0x%hx\n", gbeGetChecksumFrom4kStruct(factoryGbeStruct8k.backup, 0xBABA), factoryGbeStruct8k.backup.checkSum); - printf("\ndeblobbed Gbe (main): calculated Gbe checksum: 0x%hx and actual GBe checksum: 0x%hx\n", gbeGetChecksumFrom4kStruct(deblobbedGbeStruct8k.main, 0xBABA), deblobbedGbeStruct8k.main.checkSum); - printf("deblobbed Gbe (backup) calculated Gbe checksum: 0x%hx and actual GBe checksum: 0x%hx\n", gbeGetChecksumFrom4kStruct(deblobbedGbeStruct8k.backup, 0xBABA), deblobbedGbeStruct8k.backup.checkSum); - - return deblobbedGbeStruct8k; -} + +unsigned short gbeGetRegionWordFrom8kBuffer(int index, char* regionData); +unsigned short gbeGetChecksumFrom8kBuffer(char* regionData, unsigned short desiredValue, char isBackup); +unsigned short gbeGetChecksumFrom4kStruct(struct GBEREGIONRECORD_4K gbeStruct4k, unsigned short desiredValue); +struct GBEREGIONRECORD_8K deblobbedGbeStructFromFactory(struct GBEREGIONRECORD_8K factoryGbeStruct8k); #endif diff --git a/resources/utilities/ich9deblob/ich9deblob.c b/resources/utilities/ich9deblob/ich9deblob.c deleted file mode 100644 index f223d44e..00000000 --- a/resources/utilities/ich9deblob/ich9deblob.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * ich9deblob.c - * This file is part of the ich9deblob utility from the libreboot project - * - * Purpose: disable and remove the ME from ich9m/gm45 machines in coreboot. - * - * Copyright (C) 2014 Steve Shenton - * Francis Rowe - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* Initially based on proof of concept by Steve Shenton. */ - -/* - * Read a factory.rom dump (ich9m/gm45 machines) and - * modify the flash descriptor to remove all regions except descriptor, - * Gbe and BIOS. Set BIOS region to full size of the ROM image (after - * the flash descriptor and gbe). Basically, deblob the descriptor. - * - * This will will generate a concatenated descriptor+gbe dump suitable - * for use in libreboot. Currently tested: ThinkPad X200 (coreboot/libreboot) - */ - -/* - * See docs/hcl/x200_remove_me.html for info plus links to datasheet (also linked below) - * - * Info about flash descriptor (read page 850 onwards): - * http://www.intel.co.uk/content/dam/doc/datasheet/io-controller-hub-9-datasheet.pdf - * - * Info about Gbe region (read whole datasheet): - * http://www.intel.co.uk/content/dam/doc/application-note/i-o-controller-hub-9m-82567lf-lm-v-nvm-map-appl-note.pdf - * https://communities.intel.com/community/wired/blog/2010/10/14/how-to-basic-eeprom-checksums - */ - -#include -#include -#include "descriptor/descriptor.h" /* structs describing what's in the descriptor region */ -#include "gbe/gbe.h" /* structs describing what's in the gbe region, plus functions that use them */ -#include "x86compatibility.c" /* compatibility checks. this utility is not portable yet. */ - -int main(int argc, char *argv[]) -{ - /* - * descriptor region. Will have an actual descriptor struct mapped to it (from the factory.rom dump) - * and then it will be modified (deblobbed) to remove the ME/AMT - */ - char factoryDescriptorBuffer[DESCRIPTORREGIONSIZE]; - struct DESCRIPTORREGIONRECORD factoryDescriptorStruct; - char deblobbedDescriptorBuffer[DESCRIPTORREGIONSIZE]; - struct DESCRIPTORREGIONRECORD deblobbedDescriptorStruct; - - /* - * gbe region. Well have actual gbe buffer mapped to it (from the factory.rom dump) - * and then it will be modified to correct the main region - */ - char factoryGbeBuffer8k[GBEREGIONSIZE_8K]; - struct GBEREGIONRECORD_8K factoryGbeStruct8k; - char deblobbedGbeBuffer8k[GBEREGIONSIZE_8K]; - struct GBEREGIONRECORD_8K deblobbedGbeStruct8k; - - /* - * Used to store the location of the Gbe - * region inside the factory.rom image. - */ - unsigned int factoryGbeRegionStart; - - /* names of the files that this utility will handle */ - char* factoryRomFilename = "factory.rom"; /* user-supplied factory.bin dump (original firmware) */ - char* deblobbedDescriptorFilename = "deblobbed_descriptor.bin"; /* descriptor+gbe: to be dd'd to beginning of a libreboot image */ - - /* Used when reading the factory.rom to extract descriptor/gbe regions */ - unsigned int bufferLength; - - /* For storing the size of the factory.rom dump in bytes */ - unsigned int factoryRomSize; - - /* - * ------------------------------------------------------------------ - * Compatibility checks. This version of ich9deblob is not yet portable. - * ------------------------------------------------------------------ - */ - - if (systemOrCompilerIncompatible(factoryDescriptorStruct, factoryGbeStruct8k)) return 1; - /* If true, fail with error message */ - - /* - * ------------------------------------------------------------------ - * Extract the descriptor and gbe regions from the factory.rom dump - * ------------------------------------------------------------------ - */ - FILE* fileStream = NULL; - fileStream = fopen(factoryRomFilename, "rb"); /* open factory.rom */ - if (NULL == fileStream) - { - printf("\nerror: could not open factory.rom\n"); - return 1; - } - printf("\nfactory.rom opened successfully\n"); - - /* - * Get the descriptor region dump from the factory.rom - * (goes in factoryDescriptorBuffer variable) - */ - bufferLength = fread(factoryDescriptorBuffer, sizeof(char), DESCRIPTORREGIONSIZE, fileStream); - if (DESCRIPTORREGIONSIZE != bufferLength) // - { - printf("\nerror: could not read descriptor from factory.rom (%i) bytes read\n", bufferLength); - return 1; - } - printf("\ndescriptor region read successfully\n"); - /* - * copy descriptor buffer into descriptor struct memory - * factoryDescriptorStruct is an instance of a struct that actually - * defines the locations of all these variables in the descriptor, - * as defined in the datasheets. This allows us to map the extracted - * descriptor over the struct so that it can then be modified - * for libreboot's purpose - */ - memcpy(&factoryDescriptorStruct, &factoryDescriptorBuffer, DESCRIPTORREGIONSIZE); - /* - * ^ the above is just for reference if needed. The modifications will be made here: - */ - memcpy(&deblobbedDescriptorStruct, &factoryDescriptorBuffer, DESCRIPTORREGIONSIZE); - - /* - * Get the gbe region dump from the factory.rom - */ - - /* - * get original GBe region location - * (it will be moved to the beginning of the flash, after the descriptor region) - * note for example, factoryGbeRegionStart is set to < + * Francis Rowe + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Initially based on proof of concept by Steve Shenton. */ + +/* + * Read a factory.rom dump (ich9m/gm45 machines) and + * modify the flash descriptor to remove all regions except descriptor, + * Gbe and BIOS. Set BIOS region to full size of the ROM image (after + * the flash descriptor and gbe). Basically, deblob the descriptor. + * + * This will will generate a concatenated descriptor+gbe dump suitable + * for use in libreboot. Currently tested: ThinkPad X200 (coreboot/libreboot) + */ + +/* + * See docs/hcl/x200_remove_me.html for info plus links to datasheet (also linked below) + * + * Info about flash descriptor (read page 850 onwards): + * http://www.intel.co.uk/content/dam/doc/datasheet/io-controller-hub-9-datasheet.pdf + * + * Info about Gbe region (read whole datasheet): + * http://www.intel.co.uk/content/dam/doc/application-note/i-o-controller-hub-9m-82567lf-lm-v-nvm-map-appl-note.pdf + * https://communities.intel.com/community/wired/blog/2010/10/14/how-to-basic-eeprom-checksums + */ + +#include +#include +#include "descriptor/descriptor.h" /* structs describing what's in the descriptor region */ +#include "gbe/gbe.h" /* structs describing what's in the gbe region */ +#include "x86compatibility.h" /* system/compiler compatibility checks. This code is not portable. */ + +int main(int argc, char *argv[]) +{ + /* + * descriptor region. Will have an actual descriptor struct mapped to it (from the factory.rom dump) + * and then it will be modified (deblobbed) to remove the ME/AMT + */ + char factoryDescriptorBuffer[DESCRIPTORREGIONSIZE]; + struct DESCRIPTORREGIONRECORD factoryDescriptorStruct; + char deblobbedDescriptorBuffer[DESCRIPTORREGIONSIZE]; + struct DESCRIPTORREGIONRECORD deblobbedDescriptorStruct; + + /* + * gbe region. Well have actual gbe buffer mapped to it (from the factory.rom dump) + * and then it will be modified to correct the main region + */ + char factoryGbeBuffer8k[GBEREGIONSIZE_8K]; + struct GBEREGIONRECORD_8K factoryGbeStruct8k; + char deblobbedGbeBuffer8k[GBEREGIONSIZE_8K]; + struct GBEREGIONRECORD_8K deblobbedGbeStruct8k; + + /* + * Used to store the location of the Gbe + * region inside the factory.rom image. + */ + unsigned int factoryGbeRegionStart; + + /* names of the files that this utility will handle */ + char* factoryRomFilename = "factory.rom"; /* user-supplied factory.bin dump (original firmware) */ + char* deblobbedDescriptorFilename = "deblobbed_descriptor.bin"; /* descriptor+gbe: to be dd'd to beginning of a libreboot image */ + + /* Used when reading the factory.rom to extract descriptor/gbe regions */ + unsigned int bufferLength; + + /* For storing the size of the factory.rom dump in bytes */ + unsigned int factoryRomSize; + + /* + * ------------------------------------------------------------------ + * Compatibility checks. This version of ich9deblob is not yet portable. + * ------------------------------------------------------------------ + */ + + if (systemOrCompilerIncompatible(factoryDescriptorStruct, factoryGbeStruct8k)) return 1; + /* If true, fail with error message */ + + /* + * ------------------------------------------------------------------ + * Extract the descriptor and gbe regions from the factory.rom dump + * ------------------------------------------------------------------ + */ + FILE* fileStream = NULL; + fileStream = fopen(factoryRomFilename, "rb"); /* open factory.rom */ + if (NULL == fileStream) + { + printf("\nerror: could not open factory.rom\n"); + return 1; + } + printf("\nfactory.rom opened successfully\n"); + + /* + * Get the descriptor region dump from the factory.rom + * (goes in factoryDescriptorBuffer variable) + */ + bufferLength = fread(factoryDescriptorBuffer, sizeof(char), DESCRIPTORREGIONSIZE, fileStream); + if (DESCRIPTORREGIONSIZE != bufferLength) // + { + printf("\nerror: could not read descriptor from factory.rom (%i) bytes read\n", bufferLength); + return 1; + } + printf("\ndescriptor region read successfully\n"); + /* + * copy descriptor buffer into descriptor struct memory + * factoryDescriptorStruct is an instance of a struct that actually + * defines the locations of all these variables in the descriptor, + * as defined in the datasheets. This allows us to map the extracted + * descriptor over the struct so that it can then be modified + * for libreboot's purpose + */ + memcpy(&factoryDescriptorStruct, &factoryDescriptorBuffer, DESCRIPTORREGIONSIZE); + /* + * ^ the above is just for reference if needed. The modifications will be made here: + */ + memcpy(&deblobbedDescriptorStruct, &factoryDescriptorBuffer, DESCRIPTORREGIONSIZE); + + /* + * Get the gbe region dump from the factory.rom + */ + + /* + * get original GBe region location + * (it will be moved to the beginning of the flash, after the descriptor region) + * note for example, factoryGbeRegionStart is set to < #include - #include "descriptor/descriptor.h" /* structs describing what's in the descriptor region */ -#include "gbe/gbe.h" /* structs describing what's in the gbe region, plus functions that use them */ +#include "gbe/gbe.h" /* structs describing what's in the gbe region */ /* * --------------------------------------------------------------------- diff --git a/resources/utilities/ich9deblob/x86compatibility.h b/resources/utilities/ich9deblob/x86compatibility.h new file mode 100644 index 00000000..bbbfda72 --- /dev/null +++ b/resources/utilities/ich9deblob/x86compatibility.h @@ -0,0 +1,33 @@ +/* + * x86compatibility.h + * This file is part of the ich9deblob utility from the libreboot project + * + * Purpose: keep gcc/make happy. no actual code here, just function definitions. + * + * Copyright (C) 2014 Steve Shenton + * Francis Rowe + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef X86COMPATIBILITY_H +#define X86COMPATIBILITY_H + +int structSizesIncorrect(struct DESCRIPTORREGIONRECORD descriptorDummy, struct GBEREGIONRECORD_8K gbe8kDummy); +int systemIsBigEndian(); +int structMembersWrongOrder(); +int structBitfieldWrongOrder(); +int systemOrCompilerIncompatible(struct DESCRIPTORREGIONRECORD descriptorStruct, struct GBEREGIONRECORD_8K gbeStruct8k); + +#endif -- cgit v1.2.3-70-g09d2