199767f8919635c4928607450d9e0abb932109ceToomas Soome/*-
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Copyright (c) 2010 Marcel Moolenaar
199767f8919635c4928607450d9e0abb932109ceToomas Soome * All rights reserved.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Redistribution and use in source and binary forms, with or without
199767f8919635c4928607450d9e0abb932109ceToomas Soome * modification, are permitted provided that the following conditions
199767f8919635c4928607450d9e0abb932109ceToomas Soome * are met:
199767f8919635c4928607450d9e0abb932109ceToomas Soome * 1. Redistributions of source code must retain the above copyright
199767f8919635c4928607450d9e0abb932109ceToomas Soome * notice, this list of conditions and the following disclaimer.
199767f8919635c4928607450d9e0abb932109ceToomas Soome * 2. Redistributions in binary form must reproduce the above copyright
199767f8919635c4928607450d9e0abb932109ceToomas Soome * notice, this list of conditions and the following disclaimer in the
199767f8919635c4928607450d9e0abb932109ceToomas Soome * documentation and/or other materials provided with the distribution.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
199767f8919635c4928607450d9e0abb932109ceToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
199767f8919635c4928607450d9e0abb932109ceToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
199767f8919635c4928607450d9e0abb932109ceToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
199767f8919635c4928607450d9e0abb932109ceToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
199767f8919635c4928607450d9e0abb932109ceToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
199767f8919635c4928607450d9e0abb932109ceToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
199767f8919635c4928607450d9e0abb932109ceToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
199767f8919635c4928607450d9e0abb932109ceToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
199767f8919635c4928607450d9e0abb932109ceToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
199767f8919635c4928607450d9e0abb932109ceToomas Soome * SUCH DAMAGE.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <sys/cdefs.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome__FBSDID("$FreeBSD$");
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <sys/param.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <sys/time.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <stddef.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <stdarg.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <bootstrap.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <efi.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <efilib.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <efiprot.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL;
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic EFI_GUID devpath_guid = DEVICE_PATH_PROTOCOL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int efipart_init(void);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int efipart_strategy(void *, int, daddr_t, size_t, size_t, char *,
199767f8919635c4928607450d9e0abb932109ceToomas Soome size_t *);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int efipart_realstrategy(void *, int, daddr_t, size_t, size_t, char *,
199767f8919635c4928607450d9e0abb932109ceToomas Soome size_t *);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int efipart_open(struct open_file *, ...);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int efipart_close(struct open_file *);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int efipart_print(int);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestruct devsw efipart_dev = {
199767f8919635c4928607450d9e0abb932109ceToomas Soome .dv_name = "part",
199767f8919635c4928607450d9e0abb932109ceToomas Soome .dv_type = DEVT_DISK,
199767f8919635c4928607450d9e0abb932109ceToomas Soome .dv_init = efipart_init,
199767f8919635c4928607450d9e0abb932109ceToomas Soome .dv_strategy = efipart_strategy,
199767f8919635c4928607450d9e0abb932109ceToomas Soome .dv_open = efipart_open,
199767f8919635c4928607450d9e0abb932109ceToomas Soome .dv_close = efipart_close,
199767f8919635c4928607450d9e0abb932109ceToomas Soome .dv_ioctl = noioctl,
199767f8919635c4928607450d9e0abb932109ceToomas Soome .dv_print = efipart_print,
199767f8919635c4928607450d9e0abb932109ceToomas Soome .dv_cleanup = NULL
199767f8919635c4928607450d9e0abb932109ceToomas Soome};
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * info structure to support bcache
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestruct pdinfo
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome int pd_unit; /* unit number */
199767f8919635c4928607450d9e0abb932109ceToomas Soome int pd_open; /* reference counter */
199767f8919635c4928607450d9e0abb932109ceToomas Soome void *pd_bcache; /* buffer cache data */
199767f8919635c4928607450d9e0abb932109ceToomas Soome};
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic struct pdinfo *pdinfo;
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int npdinfo = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define PD(dev) (pdinfo[(dev)->d_unit])
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomeefipart_init(void)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_BLOCK_IO *blkio;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_DEVICE_PATH *devpath, *devpathcpy, *tmpdevpath, *node;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_HANDLE *hin, *hout, *aliases, handle;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_STATUS status;
199767f8919635c4928607450d9e0abb932109ceToomas Soome UINTN sz;
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_int n, nin, nout;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int err;
199767f8919635c4928607450d9e0abb932109ceToomas Soome size_t devpathlen;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome sz = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome hin = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, 0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (status == EFI_BUFFER_TOO_SMALL) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome hin = (EFI_HANDLE *)malloc(sz * 3);
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz,
199767f8919635c4928607450d9e0abb932109ceToomas Soome hin);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (EFI_ERROR(status))
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(hin);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (EFI_ERROR(status))
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (efi_status_to_errno(status));
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Filter handles to only include illumos partitions. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome nin = sz / sizeof(EFI_HANDLE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome hout = hin + nin;
199767f8919635c4928607450d9e0abb932109ceToomas Soome aliases = hout + nin;
199767f8919635c4928607450d9e0abb932109ceToomas Soome nout = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome bzero(aliases, nin * sizeof(EFI_HANDLE));
199767f8919635c4928607450d9e0abb932109ceToomas Soome pdinfo = malloc(nin * sizeof(*pdinfo));
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (pdinfo == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (ENOMEM);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (n = 0; n < nin; n++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = BS->HandleProtocol(hin[n], &devpath_guid,
199767f8919635c4928607450d9e0abb932109ceToomas Soome (void **)&devpath);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (EFI_ERROR(status)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome node = devpath;
199767f8919635c4928607450d9e0abb932109ceToomas Soome devpathlen = DevicePathNodeLength(node);
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (!IsDevicePathEnd(NextDevicePathNode(node))) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome node = NextDevicePathNode(node);
199767f8919635c4928607450d9e0abb932109ceToomas Soome devpathlen += DevicePathNodeLength(node);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome devpathlen += DevicePathNodeLength(NextDevicePathNode(node));
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = BS->HandleProtocol(hin[n], &blkio_guid,
199767f8919635c4928607450d9e0abb932109ceToomas Soome (void**)&blkio);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (EFI_ERROR(status))
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (!blkio->Media->LogicalPartition)
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * If we come across a logical partition of subtype CDROM
199767f8919635c4928607450d9e0abb932109ceToomas Soome * it doesn't refer to the CD filesystem itself, but rather
199767f8919635c4928607450d9e0abb932109ceToomas Soome * to any usable El Torito boot image on it. In this case
199767f8919635c4928607450d9e0abb932109ceToomas Soome * we try to find the parent device and add that instead as
199767f8919635c4928607450d9e0abb932109ceToomas Soome * that will be the CD filesystem.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
199767f8919635c4928607450d9e0abb932109ceToomas Soome DevicePathSubType(node) == MEDIA_CDROM_DP) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome devpathcpy = malloc(devpathlen);
199767f8919635c4928607450d9e0abb932109ceToomas Soome memcpy(devpathcpy, devpath, devpathlen);
199767f8919635c4928607450d9e0abb932109ceToomas Soome node = devpathcpy;
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (!IsDevicePathEnd(NextDevicePathNode(node)))
199767f8919635c4928607450d9e0abb932109ceToomas Soome node = NextDevicePathNode(node);
199767f8919635c4928607450d9e0abb932109ceToomas Soome SetDevicePathEndNode(node);
199767f8919635c4928607450d9e0abb932109ceToomas Soome tmpdevpath = devpathcpy;
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = BS->LocateDevicePath(&blkio_guid, &tmpdevpath,
199767f8919635c4928607450d9e0abb932109ceToomas Soome &handle);
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(devpathcpy);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (EFI_ERROR(status))
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome hout[nout] = handle;
199767f8919635c4928607450d9e0abb932109ceToomas Soome aliases[nout] = hin[n];
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else
199767f8919635c4928607450d9e0abb932109ceToomas Soome hout[nout] = hin[n];
199767f8919635c4928607450d9e0abb932109ceToomas Soome nout++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pdinfo[npdinfo].pd_open = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pdinfo[npdinfo].pd_bcache = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pdinfo[npdinfo].pd_unit = npdinfo;
199767f8919635c4928607450d9e0abb932109ceToomas Soome npdinfo++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome bcache_add_dev(npdinfo);
199767f8919635c4928607450d9e0abb932109ceToomas Soome err = efi_register_handles(&efipart_dev, hout, aliases, nout);
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(hin);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (err);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomeefipart_print(int verbose)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome char line[80];
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_BLOCK_IO *blkio;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_HANDLE h;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_STATUS status;
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_int unit;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int ret = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (unit = 0, h = efi_find_handle(&efipart_dev, 0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome h != NULL; h = efi_find_handle(&efipart_dev, ++unit)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome sprintf(line, " %s%d:", efipart_dev.dv_name, unit);
199767f8919635c4928607450d9e0abb932109ceToomas Soome ret = pager_output(line);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = BS->HandleProtocol(h, &blkio_guid, (void **)&blkio);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (!EFI_ERROR(status)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome sprintf(line, " %llu blocks",
199767f8919635c4928607450d9e0abb932109ceToomas Soome (unsigned long long)(blkio->Media->LastBlock + 1));
199767f8919635c4928607450d9e0abb932109ceToomas Soome ret = pager_output(line);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (blkio->Media->RemovableMedia)
199767f8919635c4928607450d9e0abb932109ceToomas Soome ret = pager_output(" (removable)");
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome ret = pager_output("\n");
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (ret != 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (ret);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomeefipart_open(struct open_file *f, ...)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome va_list args;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct devdesc *dev;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_BLOCK_IO *blkio;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_HANDLE h;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_STATUS status;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome va_start(args, f);
199767f8919635c4928607450d9e0abb932109ceToomas Soome dev = va_arg(args, struct devdesc*);
199767f8919635c4928607450d9e0abb932109ceToomas Soome va_end(args);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome h = efi_find_handle(&efipart_dev, dev->d_unit);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (h == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EINVAL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = BS->HandleProtocol(h, &blkio_guid, (void **)&blkio);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (EFI_ERROR(status))
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (efi_status_to_errno(status));
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (!blkio->Media->MediaPresent)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EAGAIN);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome dev->d_opendata = blkio;
199767f8919635c4928607450d9e0abb932109ceToomas Soome PD(dev).pd_open++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (PD(dev).pd_bcache == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome PD(dev).pd_bcache = bcache_allocate();
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomeefipart_close(struct open_file *f)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct devdesc *dev;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome dev = (struct devdesc *)(f->f_devdata);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (dev->d_opendata == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EINVAL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome dev->d_opendata = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome PD(dev).pd_open--;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (PD(dev).pd_open == 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome bcache_free(PD(dev).pd_bcache);
199767f8919635c4928607450d9e0abb932109ceToomas Soome PD(dev).pd_bcache = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * efipart_readwrite()
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Internal equivalent of efipart_strategy(), which operates on the
199767f8919635c4928607450d9e0abb932109ceToomas Soome * media-native block size. This function expects all I/O requests
199767f8919635c4928607450d9e0abb932109ceToomas Soome * to be within the media size and returns an error if such is not
199767f8919635c4928607450d9e0abb932109ceToomas Soome * the case.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomeefipart_readwrite(EFI_BLOCK_IO *blkio, int rw, daddr_t blk, daddr_t nblks,
199767f8919635c4928607450d9e0abb932109ceToomas Soome char *buf)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_STATUS status;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (blkio == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (ENXIO);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (blk < 0 || blk > blkio->Media->LastBlock)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EIO);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((blk + nblks - 1) > blkio->Media->LastBlock)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EIO);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome switch (rw) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome case F_READ:
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = blkio->ReadBlocks(blkio, blkio->Media->MediaId, blk,
199767f8919635c4928607450d9e0abb932109ceToomas Soome nblks * blkio->Media->BlockSize, buf);
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome case F_WRITE:
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (blkio->Media->ReadOnly)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EROFS);
199767f8919635c4928607450d9e0abb932109ceToomas Soome status = blkio->WriteBlocks(blkio, blkio->Media->MediaId, blk,
199767f8919635c4928607450d9e0abb932109ceToomas Soome nblks * blkio->Media->BlockSize, buf);
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome default:
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (ENOSYS);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (EFI_ERROR(status))
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("%s: rw=%d, status=%lu\n", __func__, rw, (u_long)status);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (efi_status_to_errno(status));
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomeefipart_strategy(void *devdata, int rw, daddr_t blk, size_t offset,
199767f8919635c4928607450d9e0abb932109ceToomas Soome size_t size, char *buf, size_t *rsize)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct bcache_devdata bcd;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct devdesc *dev;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome dev = (struct devdesc *)devdata;
199767f8919635c4928607450d9e0abb932109ceToomas Soome bcd.dv_strategy = efipart_realstrategy;
199767f8919635c4928607450d9e0abb932109ceToomas Soome bcd.dv_devdata = devdata;
199767f8919635c4928607450d9e0abb932109ceToomas Soome bcd.dv_cache = PD(dev).pd_bcache;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (bcache_strategy(&bcd, rw, blk, offset, size,
199767f8919635c4928607450d9e0abb932109ceToomas Soome buf, rsize));
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomeefipart_realstrategy(void *devdata, int rw, daddr_t blk, size_t offset,
199767f8919635c4928607450d9e0abb932109ceToomas Soome size_t size, char *buf, size_t *rsize)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct devdesc *dev = (struct devdesc *)devdata;
199767f8919635c4928607450d9e0abb932109ceToomas Soome EFI_BLOCK_IO *blkio;
199767f8919635c4928607450d9e0abb932109ceToomas Soome off_t off;
199767f8919635c4928607450d9e0abb932109ceToomas Soome char *blkbuf;
199767f8919635c4928607450d9e0abb932109ceToomas Soome size_t blkoff, blksz;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int error;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (dev == NULL || blk < 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EINVAL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome blkio = dev->d_opendata;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (blkio == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (ENXIO);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (size == 0 || (size % 512) != 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EIO);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome off = blk * 512;
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* make sure we don't read past disk end */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((off + size) / blkio->Media->BlockSize - 1 >
199767f8919635c4928607450d9e0abb932109ceToomas Soome blkio->Media->LastBlock) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome size = blkio->Media->LastBlock + 1 -
199767f8919635c4928607450d9e0abb932109ceToomas Soome off / blkio->Media->BlockSize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome size = size * blkio->Media->BlockSize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (rsize != NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome *rsize = size;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (blkio->Media->BlockSize == 512)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (efipart_readwrite(blkio, rw, blk, size / 512, buf));
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * The block size of the media is not 512B per sector.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome blkbuf = malloc(blkio->Media->BlockSize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (blkbuf == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (ENOMEM);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome error = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome blk = off / blkio->Media->BlockSize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome blkoff = off % blkio->Media->BlockSize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome blksz = blkio->Media->BlockSize - blkoff;
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (size > 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome error = efipart_readwrite(blkio, rw, blk, 1, blkbuf);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (error)
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (size < blksz)
199767f8919635c4928607450d9e0abb932109ceToomas Soome blksz = size;
199767f8919635c4928607450d9e0abb932109ceToomas Soome bcopy(blkbuf + blkoff, buf, blksz);
199767f8919635c4928607450d9e0abb932109ceToomas Soome buf += blksz;
199767f8919635c4928607450d9e0abb932109ceToomas Soome size -= blksz;
199767f8919635c4928607450d9e0abb932109ceToomas Soome blk++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome blkoff = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome blksz = blkio->Media->BlockSize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(blkbuf);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (error);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}