util/nvmutil: support 16kb and 128kb gbe files
See: https://edc.intel.com/content/www/us/en/design/ipla/software-development-platforms/client/platforms/alder-lake-mobile-p/intel-600-series-chipset-family-on-package-platform-controller-hub-pch-datash/spi0-for-flash/ The rules described there are universal, and replicated elsewhere for many other platforms. The rules are simply: * Flash descriptor is one block size, e.g. 4KB * GbE is two block sizes, so if IfD is 4KB, GbE is 8KB Intel defines 16KB and 128KB GbE files in specs, pertaining to 8KB and 64KB block sizes respectively. The minimum size is 4KB blocksize, for 8KB GbE files which we already supported. On larger block sizes, the same 4KB parts are observed: a single 4KB IfD area at the start of the block, and: 4KB GbE part at the start of the GbE region, and: 4KB GbE part at the start of GbE region plus block size The empty space inbetween is padding, and we ignore it, except when running swap/copy commands. The nvmutil code has been modified, to create a 128KB buffer in memory instead of 8KB, for loading GbE files. Partsize is set to GbE file size divided by 2, and only the area of memory we need to use is mapped; for example, if we're loading a 8KB GbE file into memory, we only touch the first 8KB part of the buffer, or first 16KB for 128KB files. In practise, we almost never see GbE files with sizes higher than 8KB, but *we have seen it*, *AND NOW IT'S SUPPORTED!" Signed-off-by: Leah Rowe <leah@libreboot.org>master
parent
a98ca5bf65
commit
c829b45c17
|
@ -24,12 +24,17 @@ uint8_t hextonum(char chs), rhex(void);
|
|||
#define COMMAND argv[2]
|
||||
#define MAC_ADDRESS argv[3]
|
||||
#define PARTN argv[3]
|
||||
#define SIZE_4KB 0x1000
|
||||
#define NVM_CHECKSUM 0xBABA
|
||||
|
||||
uint16_t buf16[SIZE_4KB], mac[3] = {0, 0, 0};
|
||||
/* gbe is two block sizes, i.e. one of the following multiplied by two: */
|
||||
#define SIZE_8KB 0x2000
|
||||
#define SIZE_16KB 0x4000
|
||||
#define SIZE_64KB 0x10000
|
||||
#define SIZE_128KB 0x20000
|
||||
|
||||
uint16_t buf16[SIZE_64KB], mac[3] = {0, 0, 0};
|
||||
uint8_t *buf = (uint8_t *) &buf16;
|
||||
size_t nf, gbe[2];
|
||||
size_t partsize, nf, gbe[2];
|
||||
uint8_t nvmPartChanged[2] = {0, 0}, skipread[2] = {0, 0};
|
||||
int e = 1, flags, rfd, fd, part, gbeFileChanged = 0;
|
||||
|
||||
|
@ -60,7 +65,7 @@ void (*cmd)(void) = NULL;
|
|||
if (fstat(f, &st) == -1) err(ERR(), "%s", l)
|
||||
|
||||
/* Macros for reading/writing the GbE file in memory */
|
||||
#define word(pos16, partnum) buf16[pos16 + (partnum << 11)]
|
||||
#define word(pos16, partnum) buf16[pos16 + (partnum * (partsize >> 1))]
|
||||
#define setWord(pos16, p, val16) if ((gbeFileChanged = 1) && \
|
||||
word(pos16, p) != val16) nvmPartChanged[p] = 1 | (word(pos16, p) = val16)
|
||||
|
||||
|
@ -151,8 +156,16 @@ openFiles(const char *path)
|
|||
{
|
||||
struct stat st;
|
||||
xopen(fd, path, flags);
|
||||
if ((st.st_size != (SIZE_4KB << 1)))
|
||||
err(errno = ECANCELED, "File `%s` not 8KiB", path);
|
||||
switch(st.st_size) {
|
||||
case SIZE_8KB:
|
||||
case SIZE_16KB:
|
||||
case SIZE_128KB:
|
||||
partsize = st.st_size >> 1;
|
||||
break;
|
||||
default:
|
||||
err(errno = ECANCELED, "Invalid file size (not 8/16/128KiB)");
|
||||
break;
|
||||
}
|
||||
xopen(rfd, "/dev/urandom", O_RDONLY);
|
||||
}
|
||||
|
||||
|
@ -161,16 +174,16 @@ void
|
|||
readGbe(void)
|
||||
{
|
||||
if ((cmd == writeGbe) || (cmd == cmd_copy))
|
||||
nf = SIZE_4KB;
|
||||
nf = partsize;
|
||||
else
|
||||
nf = 128;
|
||||
skipread[part ^ 1] = (cmd == cmd_copy) | (cmd == cmd_setchecksum)
|
||||
| (cmd == cmd_brick);
|
||||
gbe[1] = (gbe[0] = (size_t) buf) + SIZE_4KB;
|
||||
gbe[1] = (gbe[0] = (size_t) buf) + partsize;
|
||||
for (int p = 0; p < 2; p++) {
|
||||
if (skipread[p])
|
||||
continue;
|
||||
err_if(pread(fd, (uint8_t *) gbe[p], nf, p << 12) == -1);
|
||||
err_if(pread(fd, (uint8_t *) gbe[p], nf, p * partsize) == -1);
|
||||
swap(p); /* handle big-endian host CPU */
|
||||
}
|
||||
}
|
||||
|
@ -329,7 +342,8 @@ writeGbe(void)
|
|||
if ((!nvmPartChanged[p]) && (cmd != writeGbe))
|
||||
continue;
|
||||
swap(p ^ x);
|
||||
err_if(pwrite(fd, (uint8_t *) gbe[p ^ x], nf, p << 12) == -1);
|
||||
err_if(pwrite(fd, (uint8_t *) gbe[p ^ x], nf, p * partsize)
|
||||
== -1);
|
||||
}
|
||||
errno = 0;
|
||||
err_if(close(fd) == -1);
|
||||
|
|
Loading…
Reference in New Issue