Example #1
0
static int 
efipart_open(struct open_file *f, ...)
{
	va_list args;
	struct devdesc *dev;
	EFI_BLOCK_IO *blkio;
	EFI_HANDLE h;
	EFI_STATUS status;

	va_start(args, f);
	dev = va_arg(args, struct devdesc*);
	va_end(args);

	h = efi_find_handle(&efipart_dev, dev->d_unit);
	if (h == NULL)
		return (EINVAL);

	status = BS->HandleProtocol(h, &blkio_guid, &blkio);
	if (EFI_ERROR(status))
		return (efi_status_to_errno(status));

	if (!blkio->Media->MediaPresent)
		return (EAGAIN);

	dev->d_opendata = blkio;
	return (0);
}
Example #2
0
/*
 * efipart_readwrite()
 * Internal equivalent of efipart_strategy(), which operates on the
 * media-native block size. This function expects all I/O requests
 * to be within the media size and returns an error if such is not
 * the case.
 */
static int
efipart_readwrite(EFI_BLOCK_IO *blkio, int rw, daddr_t blk, daddr_t nblks,
    char *buf)
{
	EFI_STATUS status;

	if (blkio == NULL)
		return (ENXIO);
	if (blk < 0 || blk > blkio->Media->LastBlock)
		return (EIO);
	if ((blk + nblks - 1) > blkio->Media->LastBlock)
		return (EIO);

	switch (rw) {
	case F_READ:
		status = blkio->ReadBlocks(blkio, blkio->Media->MediaId, blk,
		    nblks * blkio->Media->BlockSize, buf);
		break;
	case F_WRITE:
		if (blkio->Media->ReadOnly)
			return (EROFS);
		status = blkio->WriteBlocks(blkio, blkio->Media->MediaId, blk,
		    nblks * blkio->Media->BlockSize, buf);
		break;
	default:
		return (ENOSYS);
	}

	if (EFI_ERROR(status))
		printf("%s: rw=%d, status=%lu\n", __func__, rw, (u_long)status);
	return (efi_status_to_errno(status));
}
Example #3
0
static int
efifs_readdir(struct open_file *f, struct dirent *d)
{
	EFI_FILE *file = f->f_fsdata;
	union fileinfo fi;
	EFI_STATUS status;
	UINTN sz;
	int i;

	if (file == NULL)
		return (EBADF);

	sz = sizeof(fi);
	status = file->Read(file, &sz, &fi);
	if (EFI_ERROR(status))
		return (efi_status_to_errno(status));
	if (sz == 0)
		return (ENOENT);

	d->d_fileno = 0;
	d->d_reclen = sizeof(*d);
	if (fi.info.Attribute & EFI_FILE_DIRECTORY)
		d->d_type = DT_DIR;
	else
		d->d_type = DT_REG;
	for (i = 0; fi.info.FileName[i] != 0; i++)
		d->d_name[i] = fi.info.FileName[i];
	d->d_name[i] = 0;
	d->d_namlen = i;
	return (0);
}
Example #4
0
static int
efifs_stat(struct open_file *f, struct stat *sb)
{
	EFI_FILE *file = f->f_fsdata;
	union fileinfo fi;
	EFI_STATUS status;
	UINTN sz;

	if (file == NULL)
		return (EBADF);

	bzero(sb, sizeof(*sb));

	sz = sizeof(fi);
	status = file->GetInfo(file, &fi_guid, &sz, &fi);
	if (EFI_ERROR(status))
		return (efi_status_to_errno(status));

	sb->st_mode = S_IRUSR | S_IRGRP | S_IROTH;
	if ((fi.info.Attribute & EFI_FILE_READ_ONLY) == 0)
		sb->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
	if (fi.info.Attribute & EFI_FILE_DIRECTORY)
		sb->st_mode |= S_IFDIR;
	else
		sb->st_mode |= S_IFREG;
	sb->st_nlink = 1;
	sb->st_atime = efi_time(&fi.info.LastAccessTime);
	sb->st_mtime = efi_time(&fi.info.ModificationTime);
	sb->st_ctime = efi_time(&fi.info.CreateTime);
	sb->st_size = fi.info.FileSize;
	sb->st_blocks = fi.info.PhysicalSize / S_BLKSIZE;
	sb->st_blksize = S_BLKSIZE;
	sb->st_birthtime = sb->st_ctime;
	return (0);
}
Example #5
0
static int
efifs_write(struct open_file *f, void *buf, size_t size, size_t *resid)
{
	EFI_FILE *file = f->f_fsdata;
	EFI_STATUS status;
	UINTN sz = size;
	char *bufp;

	if (file == NULL)
		return (EBADF);

	bufp = buf;
	while (size > 0) {
		sz = size;
		if (sz > EFI_BLOCK_SIZE)
			sz = EFI_BLOCK_SIZE;
		status = file->Write(file, &sz, bufp);
		if (EFI_ERROR(status))
			return (efi_status_to_errno(status));
		if (sz == 0)
			break;
		size -= sz;
		bufp += sz;
	}
	if (resid)
		*resid = size;
	return (0);
}
Example #6
0
int
efi_var_nextname(size_t *namesize, efi_char *name, struct uuid *vendor)
{
	efi_status status;

	status = efi_runtime->rt_scanvar(namesize, name, vendor);
	return (efi_status_to_errno(status));
}
Example #7
0
int
efi_var_set(efi_char *name, struct uuid *vendor, uint32_t attrib,
    size_t datasize, void *data)
{
	efi_status status;
 
	status = efi_runtime->rt_setvar(name, vendor, attrib, datasize, data);
	return (efi_status_to_errno(status));
}
Example #8
0
/*
 * Print information about disks
 */
static void
efifs_dev_print(int verbose)
{
	union {
		EFI_FILE_SYSTEM_INFO info;
		char buffer[1024];
	} fi;
	char line[80];
	EFI_FILE_IO_INTERFACE *fsif;
	EFI_FILE *volume;
	EFI_HANDLE h;
	EFI_STATUS status;
	UINTN sz;
	int i, unit;

	for (unit = 0, h = efi_find_handle(&efifs_dev, 0);
	    h != NULL; h = efi_find_handle(&efifs_dev, ++unit)) {
		sprintf(line, "    %s%d: ", efifs_dev.dv_name, unit);
		pager_output(line);

		status = BS->HandleProtocol(h, &sfs_guid, (VOID **)&fsif);
		if (EFI_ERROR(status))
			goto err;

		status = fsif->OpenVolume(fsif, &volume);
		if (EFI_ERROR(status))
			goto err;

		sz = sizeof(fi);
		status = volume->GetInfo(volume, &fs_guid, &sz, &fi);
		volume->Close(volume);
		if (EFI_ERROR(status))
			goto err;

		if (fi.info.ReadOnly)
			pager_output("[RO] ");
		else
			pager_output("     ");
		for (i = 0; fi.info.VolumeLabel[i] != 0; i++)
			fi.buffer[i] = fi.info.VolumeLabel[i];
		fi.buffer[i] = 0;
		if (fi.buffer[0] != 0)
			pager_output(fi.buffer);
		else
			pager_output("EFI filesystem");
		pager_output("\n");
		continue;

	err:
		sprintf(line, "[--] error %d: unable to obtain information\n",
		    efi_status_to_errno(status));
		pager_output(line);
	}
}
Example #9
0
static int
efipart_init(void) 
{
	EFI_BLOCK_IO *blkio;
	EFI_HANDLE *hin, *hout;
	EFI_STATUS status;
	UINTN sz;
	u_int n, nin, nout;
	int err;

	sz = 0;
	hin = NULL;
	status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, 0);
	if (status == EFI_BUFFER_TOO_SMALL) {
		hin = (EFI_HANDLE *)malloc(sz * 2);
		status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz,
		    hin);
		if (EFI_ERROR(status))
			free(hin);
	}
	if (EFI_ERROR(status))
		return (efi_status_to_errno(status));

	/* Filter handles to only include FreeBSD partitions. */
	nin = sz / sizeof(EFI_HANDLE);
	hout = hin + nin;
	nout = 0;

	for (n = 0; n < nin; n++) {
		status = BS->HandleProtocol(hin[n], &blkio_guid, &blkio);
		if (EFI_ERROR(status))
			continue;
		if (!blkio->Media->LogicalPartition)
			continue;
		hout[nout] = hin[n];
		nout++;
	}

	err = efi_register_handles(&efipart_dev, hout, nout);
	free(hin);
	return (err);
}
Example #10
0
static int
efifs_dev_init(void) 
{
	EFI_HANDLE *handles;
	EFI_STATUS status;
	UINTN sz;
	int err;

	sz = 0;
	status = BS->LocateHandle(ByProtocol, &sfs_guid, 0, &sz, 0);
	if (status == EFI_BUFFER_TOO_SMALL) {
		handles = (EFI_HANDLE *)malloc(sz);
		status = BS->LocateHandle(ByProtocol, &sfs_guid, 0, &sz,
		    handles);
		if (EFI_ERROR(status))
			free(handles);
	}
	if (EFI_ERROR(status))
		return (efi_status_to_errno(status));
	err = efi_register_handles(&efifs_dev, handles,
	    sz / sizeof(EFI_HANDLE));
	free(handles);
	return (err);
}
Example #11
0
static int
efinet_dev_init(void)
{
	struct netif_dif *dif;
	struct netif_stats *stats;
	EFI_HANDLE *handles;
	EFI_STATUS status;
	UINTN sz;
	int err, i, nifs;

	sz = 0;
	handles = NULL;
	status = BS->LocateHandle(ByProtocol, &sn_guid, 0, &sz, 0);
	if (status == EFI_BUFFER_TOO_SMALL) {
		handles = (EFI_HANDLE *)malloc(sz);
		status = BS->LocateHandle(ByProtocol, &sn_guid, 0, &sz,
		    handles);
		if (EFI_ERROR(status))
			free(handles);
	}
	if (EFI_ERROR(status))
		return (efi_status_to_errno(status));
	nifs = sz / sizeof(EFI_HANDLE);
	err = efi_register_handles(&efinet_dev, handles, NULL, nifs);
	free(handles);
	if (err != 0)
		return (err);

	efinetif.netif_nifs = nifs;
	efinetif.netif_ifs = calloc(nifs, sizeof(struct netif_dif));

	stats = calloc(nifs, sizeof(struct netif_stats));

	for (i = 0; i < nifs; i++) {
		EFI_SIMPLE_NETWORK *net;
		EFI_HANDLE h;

		dif = &efinetif.netif_ifs[i];
		dif->dif_unit = -1;

		h = efi_find_handle(&efinet_dev, i);

		/*
		 * Open the network device in exclusive mode. Without this
		 * we will be racing with the UEFI network stack. It will
		 * pull packets off the network leading to lost packets.
		 */
		status = BS->OpenProtocol(h, &sn_guid, (void **)&net,
		    IH, 0, EFI_OPEN_PROTOCOL_EXCLUSIVE);
		if (status != EFI_SUCCESS) {
			printf("Unable to open network interface %d for "
			    "exclusive access\n", i);
		}

		dif->dif_unit = i;
		dif->dif_nsel = 1;
		dif->dif_stats = &stats[i];
		dif->dif_private = h;
	}

	return (0);
}
Example #12
0
static int
efipart_init(void) 
{
	EFI_BLOCK_IO *blkio;
	EFI_DEVICE_PATH *devpath, *devpathcpy, *tmpdevpath, *node;
	EFI_HANDLE *hin, *hout, *aliases, handle;
	EFI_STATUS status;
	UINTN sz;
	u_int n, nin, nout;
	int err;
	size_t devpathlen;

	sz = 0;
	hin = NULL;
	status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, 0);
	if (status == EFI_BUFFER_TOO_SMALL) {
		hin = (EFI_HANDLE *)malloc(sz * 3);
		status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz,
		    hin);
		if (EFI_ERROR(status))
			free(hin);
	}
	if (EFI_ERROR(status))
		return (efi_status_to_errno(status));

	/* Filter handles to only include FreeBSD partitions. */
	nin = sz / sizeof(EFI_HANDLE);
	hout = hin + nin;
	aliases = hout + nin;
	nout = 0;

	bzero(aliases, nin * sizeof(EFI_HANDLE));

	for (n = 0; n < nin; n++) {
		status = BS->HandleProtocol(hin[n], &devpath_guid,
		    (void **)&devpath);
		if (EFI_ERROR(status)) {
			continue;
		}

		node = devpath;
		devpathlen = DevicePathNodeLength(node);
		while (!IsDevicePathEnd(NextDevicePathNode(node))) {
			node = NextDevicePathNode(node);
			devpathlen += DevicePathNodeLength(node);
		}
		devpathlen += DevicePathNodeLength(NextDevicePathNode(node));

		status = BS->HandleProtocol(hin[n], &blkio_guid,
		    (void**)&blkio);
		if (EFI_ERROR(status))
			continue;
		if (!blkio->Media->LogicalPartition)
			continue;

		/*
		 * If we come across a logical partition of subtype CDROM
		 * it doesn't refer to the CD filesystem itself, but rather
		 * to any usable El Torito boot image on it. In this case
		 * we try to find the parent device and add that instead as
		 * that will be the CD filesystem.
		 */
		if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
		    DevicePathSubType(node) == MEDIA_CDROM_DP) {
			devpathcpy = malloc(devpathlen);
			memcpy(devpathcpy, devpath, devpathlen);
			node = devpathcpy;
			while (!IsDevicePathEnd(NextDevicePathNode(node)))
				node = NextDevicePathNode(node);
			SetDevicePathEndNode(node);
			tmpdevpath = devpathcpy;
			status = BS->LocateDevicePath(&blkio_guid, &tmpdevpath,
			    &handle);
			free(devpathcpy);
			if (EFI_ERROR(status))
				continue;
			hout[nout] = handle;
			aliases[nout] = hin[n];
		} else
			hout[nout] = hin[n];
		nout++;
	}

	err = efi_register_handles(&efipart_dev, hout, aliases, nout);
	free(hin);
	return (err);
}
Example #13
0
int
efi_set_time(struct efi_tm *tm)
{

	return (efi_status_to_errno(efi_runtime->rt_settime(tm)));
}
Example #14
0
static int
efipart_init(void) 
{
	EFI_BLOCK_IO *blkio;
	EFI_DEVICE_PATH *devpath, *devpathcpy, *tmpdevpath, *node;
	EFI_HANDLE *hin, *hout, *aliases, handle;
	EFI_STATUS status;
	UINTN sz;
	u_int n, nin, nout, nrdisk;
	int err;

	sz = 0;
	hin = NULL;
	status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, 0);
	if (status == EFI_BUFFER_TOO_SMALL) {
		hin = (EFI_HANDLE *)malloc(sz * 3);
		status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz,
		    hin);
		if (EFI_ERROR(status))
			free(hin);
	}
	if (EFI_ERROR(status))
		return (efi_status_to_errno(status));

	/* Filter handles to only include FreeBSD partitions. */
	nin = sz / sizeof(EFI_HANDLE);
	hout = hin + nin;
	aliases = hout + nin;
	nout = 0;
	nrdisk = 0;

	bzero(aliases, nin * sizeof(EFI_HANDLE));
	pdinfo = malloc(nin * sizeof(*pdinfo));
	if (pdinfo == NULL)
		return (ENOMEM);

	for (n = 0; n < nin; n++) {
		devpath = efi_lookup_devpath(hin[n]);
		if (devpath == NULL) {
			continue;
		}

		status = BS->HandleProtocol(hin[n], &blkio_guid,
		    (void**)&blkio);
		if (EFI_ERROR(status))
			continue;
		if (!blkio->Media->LogicalPartition) {
			nrdisk++;
			continue;
		}

		/*
		 * If we come across a logical partition of subtype CDROM
		 * it doesn't refer to the CD filesystem itself, but rather
		 * to any usable El Torito boot image on it. In this case
		 * we try to find the parent device and add that instead as
		 * that will be the CD filesystem.
		 */
		node = efi_devpath_last_node(devpath);
		if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
		    DevicePathSubType(node) == MEDIA_CDROM_DP) {
			devpathcpy = efi_devpath_trim(devpath);
			tmpdevpath = devpathcpy;
			status = BS->LocateDevicePath(&blkio_guid, &tmpdevpath,
			    &handle);
			free(devpathcpy);
			if (EFI_ERROR(status))
				continue;
			hout[nout] = handle;
			aliases[nout] = hin[n];
		} else
			hout[nout] = hin[n];
		nout++;
		pdinfo[npdinfo].pd_open = 0;
		pdinfo[npdinfo].pd_bcache = NULL;
		pdinfo[npdinfo].pd_unit = npdinfo;
		npdinfo++;
	}

	bcache_add_dev(npdinfo);
	err = efi_register_handles(&efipart_dev, hout, aliases, nout);
	free(hin);

	if (nout == 0 && nrdisk > 0)
		printf("Found %d disk(s) but no logical partition\n", nrdisk);
	return (err);
}
Example #15
0
static int
efifs_open(const char *upath, struct open_file *f)
{
	struct devdesc *dev = f->f_devdata;
	EFI_FILE_IO_INTERFACE *fsif;
	EFI_FILE *file, *root;
	EFI_HANDLE h;
	EFI_STATUS status;
	CHAR16 *cp, *path;

	if (f->f_dev != &efifs_dev || dev->d_unit < 0)
		return (EINVAL);

	h = efi_find_handle(f->f_dev, dev->d_unit);
	if (h == NULL)
		return (EINVAL);

	status = BS->HandleProtocol(h, &sfs_guid, (VOID **)&fsif);
	if (EFI_ERROR(status))
		return (efi_status_to_errno(status));

	/* Get the root directory. */
	status = fsif->OpenVolume(fsif, &root);
	if (EFI_ERROR(status))
		return (efi_status_to_errno(status));

	while (*upath == '/')
		upath++;

	/* Special case: opening the root directory. */
	if (*upath == '\0') {
		f->f_fsdata = root;
		return (0);
	}

	path = malloc((strlen(upath) + 1) * sizeof(CHAR16));
	if (path == NULL) {
		root->Close(root);
		return (ENOMEM);
	}

	cp = path;
	while (*upath != '\0') {
		if (*upath == '/') {
			*cp = '\\';
			while (upath[1] == '/')
				upath++;
		} else
			*cp = *upath;
		upath++;
		cp++;
	}
	*cp = 0;

	/* Open the file. */
	status = root->Open(root, &file, path,
	    EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);
	if (status == EFI_ACCESS_DENIED || status == EFI_WRITE_PROTECTED)
		status = root->Open(root, &file, path, EFI_FILE_MODE_READ, 0);
	free(path);
	root->Close(root);
	if (EFI_ERROR(status))
		return (efi_status_to_errno(status));

	f->f_fsdata = file;
	return (0);
}
Example #16
0
static int
efinet_dev_init()
{
	struct netif_dif *dif;
	struct netif_stats *stats;
	EFI_DEVICE_PATH *devpath, *node;
	EFI_SIMPLE_NETWORK *net;
	EFI_HANDLE *handles, *handles2;
	EFI_STATUS status;
	UINTN sz;
	int err, i, nifs;
	extern struct devsw netdev;

	sz = 0;
	handles = NULL;
	status = BS->LocateHandle(ByProtocol, &sn_guid, NULL, &sz, NULL);
	if (status == EFI_BUFFER_TOO_SMALL) {
		handles = (EFI_HANDLE *)malloc(sz);
		status = BS->LocateHandle(ByProtocol, &sn_guid, NULL, &sz,
		    handles);
		if (EFI_ERROR(status))
			free(handles);
	}
	if (EFI_ERROR(status))
		return (efi_status_to_errno(status));
	handles2 = (EFI_HANDLE *)malloc(sz);
	if (handles2 == NULL) {
		free(handles);
		return (ENOMEM);
	}
	nifs = 0;
	for (i = 0; i < sz / sizeof(EFI_HANDLE); i++) {
		devpath = efi_lookup_devpath(handles[i]);
		if (devpath == NULL)
			continue;
		if ((node = efi_devpath_last_node(devpath)) == NULL)
			continue;

		if (DevicePathType(node) != MESSAGING_DEVICE_PATH ||
		    DevicePathSubType(node) != MSG_MAC_ADDR_DP)
			continue;

		/*
		 * Open the network device in exclusive mode. Without this
		 * we will be racing with the UEFI network stack. It will
		 * pull packets off the network leading to lost packets.
		 */
		status = BS->OpenProtocol(handles[i], &sn_guid, (void **)&net,
		    IH, NULL, EFI_OPEN_PROTOCOL_EXCLUSIVE);
		if (status != EFI_SUCCESS) {
			printf("Unable to open network interface %d for "
			    "exclusive access: %lu\n", i,
			    EFI_ERROR_CODE(status));
		}

		handles2[nifs] = handles[i];
		nifs++;
	}
	free(handles);
	if (nifs == 0) {
		err = ENOENT;
		goto done;
	}

	err = efi_register_handles(&efinet_dev, handles2, NULL, nifs);
	if (err != 0)
		goto done;

	efinetif.netif_ifs = calloc(nifs, sizeof(struct netif_dif));
	stats = calloc(nifs, sizeof(struct netif_stats));
	if (efinetif.netif_ifs == NULL || stats == NULL) {
		free(efinetif.netif_ifs);
		free(stats);
		efinetif.netif_ifs = NULL;
		err = ENOMEM;
		goto done;
	}
	efinetif.netif_nifs = nifs;

	for (i = 0; i < nifs; i++) {

		dif = &efinetif.netif_ifs[i];
		dif->dif_unit = i;
		dif->dif_nsel = 1;
		dif->dif_stats = &stats[i];
		dif->dif_private = handles2[i];
	}

	efinet_dev.dv_open = netdev.dv_open;
	efinet_dev.dv_close = netdev.dv_close;
	efinet_dev.dv_strategy = netdev.dv_strategy;

done:
	free(handles2);
	return (err);
}