mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-19 10:53:58 +00:00
Fix EFI UFS caching
EFI was mixing caching in two separate places causing issues when multiple partitions where tested. Eliminate this by removing fsstat and re-factoring fsread into fsread_size, adding basic parameter validation. Also: * Enhance some error print outs. * Fix compilation under UFS1_ONLY and UFS2_ONLY * Use sizeof on vars instead of structs. * Add basic parameter validation to fsread_size. MFC after: 1 week X-MFC-With: r293268 Sponsored by: Multiplay Differential Revision: https://reviews.freebsd.org/D4989
This commit is contained in:
parent
405b75f94c
commit
ba76113f61
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=294493
@ -165,7 +165,7 @@ static int sblock_try[] = SBLOCKSEARCH;
|
||||
#endif
|
||||
|
||||
static ssize_t
|
||||
fsread(ufs_ino_t inode, void *buf, size_t nbyte)
|
||||
fsread_size(ufs_ino_t inode, void *buf, size_t nbyte, size_t *fsizep)
|
||||
{
|
||||
#ifndef UFS2_ONLY
|
||||
static struct ufs1_dinode dp1;
|
||||
@ -185,6 +185,10 @@ fsread(ufs_ino_t inode, void *buf, size_t nbyte)
|
||||
static ufs2_daddr_t blkmap, indmap;
|
||||
u_int u;
|
||||
|
||||
/* Basic parameter validation. */
|
||||
if ((buf == NULL && nbyte != 0) || dmadat == NULL)
|
||||
return (-1);
|
||||
|
||||
blkbuf = dmadat->blkbuf;
|
||||
indbuf = dmadat->indbuf;
|
||||
|
||||
@ -231,18 +235,18 @@ fsread(ufs_ino_t inode, void *buf, size_t nbyte)
|
||||
return -1;
|
||||
n = INO_TO_VBO(n, inode);
|
||||
#if defined(UFS1_ONLY)
|
||||
memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n,
|
||||
sizeof(struct ufs1_dinode));
|
||||
memcpy(&dp1, (struct ufs1_dinode *)(void *)blkbuf + n,
|
||||
sizeof(dp1));
|
||||
#elif defined(UFS2_ONLY)
|
||||
memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n,
|
||||
sizeof(struct ufs2_dinode));
|
||||
memcpy(&dp2, (struct ufs2_dinode *)(void *)blkbuf + n,
|
||||
sizeof(dp2));
|
||||
#else
|
||||
if (fs.fs_magic == FS_UFS1_MAGIC)
|
||||
memcpy(&dp1, (struct ufs1_dinode *)(void *)blkbuf + n,
|
||||
sizeof(struct ufs1_dinode));
|
||||
sizeof(dp1));
|
||||
else
|
||||
memcpy(&dp2, (struct ufs2_dinode *)(void *)blkbuf + n,
|
||||
sizeof(struct ufs2_dinode));
|
||||
sizeof(dp2));
|
||||
#endif
|
||||
inomap = inode;
|
||||
fs_off = 0;
|
||||
@ -306,5 +310,17 @@ fsread(ufs_ino_t inode, void *buf, size_t nbyte)
|
||||
fs_off += n;
|
||||
nb -= n;
|
||||
}
|
||||
|
||||
if (fsizep != NULL)
|
||||
*fsizep = size;
|
||||
|
||||
return nbyte;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
fsread(ufs_ino_t inode, void *buf, size_t nbyte)
|
||||
{
|
||||
|
||||
return fsread_size(inode, buf, nbyte, NULL);
|
||||
}
|
||||
|
||||
|
@ -68,93 +68,23 @@ dskread(void *buf, u_int64_t lba, int nblk)
|
||||
|
||||
#include "ufsread.c"
|
||||
|
||||
static ssize_t
|
||||
fsstat(ufs_ino_t inode)
|
||||
{
|
||||
#ifndef UFS2_ONLY
|
||||
static struct ufs1_dinode dp1;
|
||||
#endif
|
||||
#ifndef UFS1_ONLY
|
||||
static struct ufs2_dinode dp2;
|
||||
#endif
|
||||
static struct fs fs;
|
||||
static ufs_ino_t inomap;
|
||||
char *blkbuf;
|
||||
void *indbuf;
|
||||
size_t n, size;
|
||||
static ufs2_daddr_t blkmap, indmap;
|
||||
|
||||
blkbuf = dmadat->blkbuf;
|
||||
indbuf = dmadat->indbuf;
|
||||
if (!dsk_meta) {
|
||||
inomap = 0;
|
||||
for (n = 0; sblock_try[n] != -1; n++) {
|
||||
if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE,
|
||||
SBLOCKSIZE / DEV_BSIZE))
|
||||
return (-1);
|
||||
memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
|
||||
if ((
|
||||
#if defined(UFS1_ONLY)
|
||||
fs.fs_magic == FS_UFS1_MAGIC
|
||||
#elif defined(UFS2_ONLY)
|
||||
(fs.fs_magic == FS_UFS2_MAGIC &&
|
||||
fs.fs_sblockloc == sblock_try[n])
|
||||
#else
|
||||
fs.fs_magic == FS_UFS1_MAGIC ||
|
||||
(fs.fs_magic == FS_UFS2_MAGIC &&
|
||||
fs.fs_sblockloc == sblock_try[n])
|
||||
#endif
|
||||
) &&
|
||||
fs.fs_bsize <= MAXBSIZE &&
|
||||
fs.fs_bsize >= (int32_t)sizeof(struct fs))
|
||||
break;
|
||||
}
|
||||
if (sblock_try[n] == -1) {
|
||||
return (-1);
|
||||
}
|
||||
dsk_meta++;
|
||||
} else
|
||||
memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
|
||||
if (!inode)
|
||||
return (0);
|
||||
if (inomap != inode) {
|
||||
n = IPERVBLK(&fs);
|
||||
if (dskread(blkbuf, INO_TO_VBA(&fs, n, inode), DBPERVBLK))
|
||||
return (-1);
|
||||
n = INO_TO_VBO(n, inode);
|
||||
#if defined(UFS1_ONLY)
|
||||
memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n,
|
||||
sizeof(struct ufs1_dinode));
|
||||
#elif defined(UFS2_ONLY)
|
||||
memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n,
|
||||
sizeof(struct ufs2_dinode));
|
||||
#else
|
||||
if (fs.fs_magic == FS_UFS1_MAGIC)
|
||||
memcpy(&dp1, (struct ufs1_dinode *)(void *)blkbuf + n,
|
||||
sizeof(struct ufs1_dinode));
|
||||
else
|
||||
memcpy(&dp2, (struct ufs2_dinode *)(void *)blkbuf + n,
|
||||
sizeof(struct ufs2_dinode));
|
||||
#endif
|
||||
inomap = inode;
|
||||
fs_off = 0;
|
||||
blkmap = indmap = 0;
|
||||
}
|
||||
size = DIP(di_size);
|
||||
n = size - fs_off;
|
||||
|
||||
return (n);
|
||||
}
|
||||
|
||||
static struct dmadat __dmadat;
|
||||
|
||||
static int
|
||||
init_dev(dev_info_t* dev)
|
||||
{
|
||||
|
||||
devinfo = dev;
|
||||
dmadat = &__dmadat;
|
||||
|
||||
return fsread(0, NULL, 0);
|
||||
}
|
||||
|
||||
static EFI_STATUS
|
||||
probe(dev_info_t* dev)
|
||||
{
|
||||
|
||||
devinfo = dev;
|
||||
dmadat = &__dmadat;
|
||||
if (fsread(0, NULL, 0) < 0)
|
||||
if (init_dev(dev) < 0)
|
||||
return (EFI_UNSUPPORTED);
|
||||
|
||||
add_device(&devices, dev);
|
||||
@ -171,14 +101,15 @@ try_load(dev_info_t *dev, const char *loader_path, void **bufp, size_t *bufsize)
|
||||
ssize_t read;
|
||||
void *buf;
|
||||
|
||||
dsk_meta = 0;
|
||||
devinfo = dev;
|
||||
if (init_dev(dev) < 0)
|
||||
return (EFI_UNSUPPORTED);
|
||||
|
||||
if ((ino = lookup(loader_path)) == 0)
|
||||
return (EFI_NOT_FOUND);
|
||||
|
||||
size = fsstat(ino);
|
||||
if (size <= 0) {
|
||||
printf("Failed to fsstat %s ino: %d\n", loader_path, ino);
|
||||
if (fsread_size(ino, NULL, 0, &size) < 0 || size <= 0) {
|
||||
printf("Failed to read size of '%s' ino: %d\n", loader_path,
|
||||
ino);
|
||||
return (EFI_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
@ -191,7 +122,7 @@ try_load(dev_info_t *dev, const char *loader_path, void **bufp, size_t *bufsize)
|
||||
|
||||
read = fsread(ino, buf, size);
|
||||
if ((size_t)read != size) {
|
||||
printf("Failed to read %s (%zd != %zu)\n", loader_path, read,
|
||||
printf("Failed to read '%s' (%zd != %zu)\n", loader_path, read,
|
||||
size);
|
||||
(void)bs->FreePool(buf);
|
||||
return (EFI_INVALID_PARAMETER);
|
||||
|
Loading…
Reference in New Issue
Block a user