Skip to content
This repository has been archived by the owner on Aug 24, 2022. It is now read-only.

Commit

Permalink
Support SCSI storage
Browse files Browse the repository at this point in the history
HyperV only support SCSI storage.
To run on HyperV, SCSI storage must be supported

Tracked-On: OAM-92157
Signed-off-by: JianFeng,Zhou <[email protected]>
  • Loading branch information
zhouji3x committed Aug 17, 2020
1 parent e4aafe0 commit 65183c4
Show file tree
Hide file tree
Showing 6 changed files with 236 additions and 20 deletions.
3 changes: 3 additions & 0 deletions include/storage.h
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ enum storage_type {
STORAGE_SATA,
STORAGE_NVME,
STORAGE_VIRTUAL,
STORAGE_ISCSI,
#ifdef USB_STORAGE
STORAGE_USB,
#endif
Expand Down Expand Up @@ -94,4 +95,6 @@ EFI_STATUS set_logical_unit(UINT64 user_lun, UINT64 factory_lun);
void print_progress(EFI_LBA done, EFI_LBA total, uint32_t sec, uint32_t *prev_sec, uint32_t *prev);
void set_exclude_device(EFI_HANDLE device);

SCSI_DEVICE_PATH* get_scsi_device_path(EFI_DEVICE_PATH *p);

#endif /* _STORAGE_H_ */
4 changes: 4 additions & 0 deletions libfastboot/fastboot_oem.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,10 @@ static void cmd_oem_set_storage(INTN argc, CHAR8 **argv)
types[total_types++] = STORAGE_NVME;
continue;
}
if (!strcmp(argv[i], (CHAR8 *)"iscsi")) {
types[total_types++] = STORAGE_ISCSI;
continue;
}
if (!strcmp(argv[i], (CHAR8 *)"sdcard")) {
types[total_types++] = STORAGE_SDCARD;
continue;
Expand Down
1 change: 1 addition & 0 deletions libkernelflinger/Android.mk
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ LOCAL_SRC_FILES := \
qsort.c \
timer.c \
nvme.c \
iscsi.c \
virtual_media.c \
general_block.c \
aes_gcm.c \
Expand Down
20 changes: 15 additions & 5 deletions libkernelflinger/android.c
Original file line number Diff line number Diff line change
Expand Up @@ -1063,17 +1063,27 @@ static EFI_STATUS setup_command_line(
PCI_DEVICE_PATH *boot_device = get_boot_device();
if (boot_device) {
CHAR16 *diskbus = NULL;
enum storage_type storage_type;
#ifdef AUTO_DISKBUS
diskbus = PoolPrint(L"%02x.%x", boot_device->Device, boot_device->Function);
#else
diskbus = PoolPrint(L"%a", (CHAR8 *)PREDEF_DISK_BUS);
#endif
StrToLower(diskbus);
ret = prepend_command_line(&cmdline16,
(aosp_header->header_version < 2)
? L"androidboot.diskbus=%s"
: L"androidboot.boot_devices=pci0000:00/0000:00:%s",
diskbus);

get_boot_device_type(&storage_type);
if(aosp_header->header_version < 2)
ret = prepend_command_line(&cmdline16,
L"androidboot.diskbus=%s",
diskbus);
else
if(storage_type == STORAGE_ISCSI)
ret = prepend_command_line(&cmdline16,
L"androidboot.boot_devices=scsi_disk/0:0:0:0");
else
ret = prepend_command_line(&cmdline16,
L"androidboot.boot_devices=pci0000:00/0000:00:%s",
diskbus);
FreePool(diskbus);
if (EFI_ERROR(ret))
goto out;
Expand Down
86 changes: 86 additions & 0 deletions libkernelflinger/iscsi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2020, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This file defines bootlogic data structures, try to keep it without
* any external definitions in order to ease export of it.
*/

#include <lib.h>
#include "storage.h"

#include "protocol/NvmExpressHci.h"
#include "protocol/DevicePath.h"
#include "protocol/NvmExpressPassthru.h"

#define ATTR_UNUSED __attribute__((unused))

#define MSG_SCSI_DP 0x02

#include "pci.h"

SCSI_DEVICE_PATH* get_scsi_device_path(EFI_DEVICE_PATH *p)
{
if (!p)
return NULL;

while (!IsDevicePathEndType(p)) {
if (DevicePathType(p) == MESSAGING_DEVICE_PATH
&& DevicePathSubType(p) == MSG_SCSI_DP)
return (SCSI_DEVICE_PATH *)p;
p = NextDevicePathNode(p);
}
return NULL;
}

static EFI_STATUS iscsi_erase_blocks(
EFI_HANDLE handle ATTR_UNUSED,
EFI_BLOCK_IO *bio ATTR_UNUSED,
EFI_LBA start ATTR_UNUSED,
EFI_LBA end ATTR_UNUSED
)
{
return EFI_UNSUPPORTED;
}

static EFI_STATUS iscsi_check_logical_unit(ATTR_UNUSED EFI_DEVICE_PATH *p, ATTR_UNUSED logical_unit_t log_unit)
{
return log_unit == LOGICAL_UNIT_USER ? EFI_SUCCESS : EFI_UNSUPPORTED;
}

static BOOLEAN is_iscsi(EFI_DEVICE_PATH *p)
{
return get_scsi_device_path(p) != NULL;
}

struct storage STORAGE(STORAGE_ISCSI) = {
.erase_blocks = iscsi_erase_blocks,
.check_logical_unit = iscsi_check_logical_unit,
.probe = is_iscsi,
.name = L"ISCSI"
};

142 changes: 127 additions & 15 deletions libkernelflinger/storage.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

static struct storage *cur_storage;
static PCI_DEVICE_PATH boot_device = { .Function = -1, .Device = -1 };
static SCSI_DEVICE_PATH boot_device_scsi = { .Pun = -1, .Lun = -1 };
static enum storage_type boot_device_type;
static BOOLEAN initialized = FALSE;
static EFI_DEVICE_PATH *exclude_device = NULL;
Expand All @@ -52,10 +53,20 @@ static BOOLEAN is_boot_device(EFI_DEVICE_PATH *p)
{
PCI_DEVICE_PATH *pci;

if (boot_device.Header.Type == 0)
if (boot_device.Header.Type == 0 && boot_device_scsi.Header.Type == 0)
return FALSE;

pci = get_pci_device_path(p);
if(pci == NULL)
{
SCSI_DEVICE_PATH *scsi = get_scsi_device_path(p);
if(scsi == NULL) {
debug(L"is_boot_device: not PCI/SCSI\n");
return 0;
}

return scsi->Pun == boot_device_scsi.Pun && scsi->Lun == boot_device_scsi.Lun;
}

return pci && pci->Function == boot_device.Function
&& pci->Device == boot_device.Device;
Expand All @@ -66,6 +77,7 @@ extern struct storage STORAGE(STORAGE_UFS);
extern struct storage STORAGE(STORAGE_SDCARD);
extern struct storage STORAGE(STORAGE_SATA);
extern struct storage STORAGE(STORAGE_NVME);
extern struct storage STORAGE(STORAGE_ISCSI);
extern struct storage STORAGE(STORAGE_VIRTUAL);
#ifdef USB_STORAGE
extern struct storage STORAGE(STORAGE_USB);
Expand All @@ -86,6 +98,7 @@ static EFI_STATUS identify_storage(EFI_DEVICE_PATH *device_path,
, &STORAGE(STORAGE_SATA)
, &STORAGE(STORAGE_NVME)
, &STORAGE(STORAGE_VIRTUAL)
, &STORAGE(STORAGE_ISCSI)
#ifdef USB_STORAGE
, &STORAGE(STORAGE_USB)
#endif
Expand Down Expand Up @@ -143,6 +156,92 @@ BOOLEAN is_same_device(EFI_DEVICE_PATH *p, EFI_DEVICE_PATH *e)
return TRUE;
}

EFI_STATUS identify_scsi_boot_device(enum storage_type filter)
{
EFI_STATUS ret;
EFI_HANDLE *handles;
UINTN nb_handle = 0;
UINTN i;
EFI_DEVICE_PATH *device_path;
SCSI_DEVICE_PATH *scsi = NULL;
struct storage *storage;
enum storage_type type;
EFI_HANDLE new_boot_device_handle = NULL;
SCSI_DEVICE_PATH new_boot_device = { .Pun = -1, .Lun = -1 };
enum storage_type new_boot_device_type;
struct storage *new_storage;

new_storage = NULL;
ret = uefi_call_wrapper(BS->LocateHandleBuffer, 5, ByProtocol,
&BlockIoProtocol, NULL, &nb_handle, &handles);
if (EFI_ERROR(ret)) {
efi_perror(ret, L"Failed to locate Block IO Protocol");
return ret;
}

new_boot_device.Header.Type = 0;
for (i = 0; i < nb_handle; i++) {
device_path = DevicePathFromHandle(handles[i]);
if (!device_path)
continue;

scsi = get_scsi_device_path(device_path);
if (!scsi)
continue;

if (is_same_device(device_path, exclude_device))
continue;

if (new_boot_device.Pun == scsi->Pun &&
new_boot_device.Lun == scsi->Lun &&
new_boot_device.Header.Type == scsi->Header.Type &&
new_boot_device.Header.SubType == scsi->Header.SubType)
continue;

ret = identify_storage(device_path, filter, &storage, &type);
if (EFI_ERROR(ret))
continue;

if (!new_boot_device.Header.Type || new_boot_device_type >= type) {
ret = memcpy_s(&new_boot_device, sizeof(new_boot_device), scsi,
sizeof(new_boot_device));
if (EFI_ERROR(ret)) {
FreePool(handles);
return ret;
}
new_boot_device_type = type;
new_storage = storage;
new_boot_device_handle = handles[i];
continue;
}

if (new_boot_device_type == type &&
type != STORAGE_GENERAL_BLOCK &&
filter > type) {
error(L"Multiple identifcal storage found! Can't make a decision");
new_storage = NULL;
new_boot_device.Header.Type = 0;
FreePool(handles);
return EFI_UNSUPPORTED;
}
}

FreePool(handles);

if (!new_storage) {
error(L"No SCSI storage found for type %d", filter);
return EFI_UNSUPPORTED;
}
cur_storage = new_storage;
boot_device_type = new_boot_device_type;
boot_device_handle = new_boot_device_handle;
boot_device_scsi = new_boot_device;

debug(L"%s storage selected", cur_storage->name);
return EFI_SUCCESS;
}


EFI_STATUS identify_boot_device(enum storage_type filter)
{
EFI_STATUS ret;
Expand Down Expand Up @@ -216,8 +315,7 @@ EFI_STATUS identify_boot_device(enum storage_type filter)
FreePool(handles);

if (!new_storage) {
error(L"No PCI storage found for type %d", filter);
return EFI_UNSUPPORTED;
return identify_scsi_boot_device(filter);
}
cur_storage = new_storage;
boot_device_type = new_boot_device_type;
Expand All @@ -236,7 +334,8 @@ static BOOLEAN valid_storage(void)
initialized = TRUE;
return !EFI_ERROR(identify_boot_device(STORAGE_ALL));
}
return boot_device.Header.Type && cur_storage;

return (boot_device.Header.Type || boot_device_scsi.Header.Type) && cur_storage;
}

static EFI_STATUS media_erase_blocks(EFI_HANDLE handle, EFI_BLOCK_IO *bio, EFI_LBA start, EFI_LBA end)
Expand Down Expand Up @@ -309,11 +408,12 @@ static EFI_STATUS media_erase_blocks(EFI_HANDLE handle, EFI_BLOCK_IO *bio, EFI_L

EFI_STATUS storage_check_logical_unit(EFI_DEVICE_PATH *p, logical_unit_t log_unit)
{
if (!valid_storage())
if (!valid_storage()) {
return EFI_UNSUPPORTED;
if (!is_boot_device(p))
}
if (!is_boot_device(p)) {
return EFI_UNSUPPORTED;

}
return cur_storage->check_logical_unit(p, log_unit);
}

Expand Down Expand Up @@ -394,27 +494,37 @@ EFI_STATUS fill_zero(EFI_BLOCK_IO *bio, EFI_LBA start, EFI_LBA end)
EFI_STATUS storage_set_boot_device(EFI_HANDLE device)
{
EFI_DEVICE_PATH *device_path = DevicePathFromHandle(device);
PCI_DEVICE_PATH *pci;
EFI_STATUS ret;
PCI_DEVICE_PATH *pci;
CHAR16 *dps;

if (!device_path) {
error(L"Failed to get device path from boot handle");
return EFI_UNSUPPORTED;
}

pci = get_pci_device_path(device_path);
if (!pci) {
error(L"Boot device is not PCI, unsupported");
return EFI_UNSUPPORTED;
}

ret = identify_storage(device_path, STORAGE_ALL, &cur_storage,
&boot_device_type);
if (EFI_ERROR(ret)) {
error(L"Boot device unsupported");
return ret;
}

pci = get_pci_device_path(device_path);
if (!pci) {
SCSI_DEVICE_PATH *scsi = get_scsi_device_path(device_path);
if(scsi == NULL) {
error(L"Only PCI/SCSI boot device is supported");
return EFI_UNSUPPORTED;
}

error(L"Setting boot device to: SCSI");
initialized = TRUE;
boot_device_scsi = *scsi;
boot_device_handle = device;
return EFI_SUCCESS;
}

dps = DevicePathToStr((EFI_DEVICE_PATH *)pci);
debug(L"Setting PCI boot device to: %s", dps);
FreePool(dps);
Expand All @@ -423,7 +533,6 @@ EFI_STATUS storage_set_boot_device(EFI_HANDLE device)
ret = memcpy_s(&boot_device, sizeof(boot_device), pci, sizeof(boot_device));
if (EFI_ERROR(ret))
return ret;

boot_device_handle = device;
return EFI_SUCCESS;
}
Expand Down Expand Up @@ -470,6 +579,9 @@ PCI_DEVICE_PATH *get_boot_device(void)
else
initialized = TRUE;
}

if(boot_device_scsi.Header.Type)
return (PCI_DEVICE_PATH *)&boot_device_scsi;
return boot_device.Header.Type == 0 ? NULL : &boot_device;
}

Expand Down

0 comments on commit 65183c4

Please sign in to comment.