From 26203300490cd0e9d85f5e66264e7b47bb5f81e7 Mon Sep 17 00:00:00 2001 From: "JianFeng,Zhou" Date: Mon, 17 Aug 2020 09:55:59 +0800 Subject: [PATCH] Support SCSI storage HyperV only support SCSI storage. To run on HyperV, SCSI storage must be supported Tracked-On: OAM-92157 Signed-off-by: JianFeng,Zhou --- include/storage.h | 3 + libfastboot/fastboot_oem.c | 4 + libkernelflinger/Android.mk | 1 + libkernelflinger/android.c | 20 +++-- libkernelflinger/iscsi.c | 100 ++++++++++++++++++++++++ libkernelflinger/storage.c | 147 ++++++++++++++++++++++++++++++++---- 6 files changed, 255 insertions(+), 20 deletions(-) mode change 100755 => 100644 include/storage.h mode change 100755 => 100644 libkernelflinger/Android.mk create mode 100644 libkernelflinger/iscsi.c diff --git a/include/storage.h b/include/storage.h old mode 100755 new mode 100644 index f633261a..d3f82e62 --- a/include/storage.h +++ b/include/storage.h @@ -43,6 +43,7 @@ enum storage_type { STORAGE_SATA, STORAGE_NVME, STORAGE_VIRTUAL, + STORAGE_ISCSI, #ifdef USB_STORAGE STORAGE_USB, #endif @@ -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_ */ diff --git a/libfastboot/fastboot_oem.c b/libfastboot/fastboot_oem.c index b3b5734e..0f609792 100644 --- a/libfastboot/fastboot_oem.c +++ b/libfastboot/fastboot_oem.c @@ -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; diff --git a/libkernelflinger/Android.mk b/libkernelflinger/Android.mk old mode 100755 new mode 100644 index 1b679731..3f740d7d --- a/libkernelflinger/Android.mk +++ b/libkernelflinger/Android.mk @@ -123,6 +123,7 @@ LOCAL_SRC_FILES := \ qsort.c \ timer.c \ nvme.c \ + iscsi.c \ virtual_media.c \ general_block.c \ aes_gcm.c \ diff --git a/libkernelflinger/android.c b/libkernelflinger/android.c index 86668c93..764a3244 100644 --- a/libkernelflinger/android.c +++ b/libkernelflinger/android.c @@ -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; diff --git a/libkernelflinger/iscsi.c b/libkernelflinger/iscsi.c new file mode 100644 index 00000000..bcf49476 --- /dev/null +++ b/libkernelflinger/iscsi.c @@ -0,0 +1,100 @@ +/* + * 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 +#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" + +#if 0 +static void *get_iscsi_device_path(EFI_DEVICE_PATH *p) +{ + for (; !IsDevicePathEndType(p); p = NextDevicePathNode(p)) { + if (DevicePathType(p) == MESSAGING_DEVICE_PATH + && DevicePathSubType(p) == MSG_SCSI_DP) + return (void *)p; + } + + return NULL; +} +#endif + +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" +}; + + diff --git a/libkernelflinger/storage.c b/libkernelflinger/storage.c index 800d2f01..1da7666b 100644 --- a/libkernelflinger/storage.c +++ b/libkernelflinger/storage.c @@ -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; @@ -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) { + Print(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; @@ -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); @@ -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 @@ -143,6 +156,93 @@ 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; + + Print(L"%s storage selected", cur_storage->name); + debug(L"%s storage selected", cur_storage->name); + return EFI_SUCCESS; +} + + EFI_STATUS identify_boot_device(enum storage_type filter) { EFI_STATUS ret; @@ -216,8 +316,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; @@ -236,7 +335,10 @@ static BOOLEAN valid_storage(void) initialized = TRUE; return !EFI_ERROR(identify_boot_device(STORAGE_ALL)); } - return boot_device.Header.Type && cur_storage; + int ret; + ret = (boot_device.Header.Type || boot_device_scsi.Header.Type) && cur_storage; + + return ret; } static EFI_STATUS media_erase_blocks(EFI_HANDLE handle, EFI_BLOCK_IO *bio, EFI_LBA start, EFI_LBA end) @@ -309,11 +411,14 @@ 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()) { + Print(L"storage_check_logical_unit: valid_storage return 0 ????\n"); return EFI_UNSUPPORTED; - if (!is_boot_device(p)) + } + if (!is_boot_device(p)) { + Print(L"is_boot_device return 0 ????\n"); return EFI_UNSUPPORTED; - + } return cur_storage->check_logical_unit(p, log_unit); } @@ -394,8 +499,8 @@ 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) { @@ -403,18 +508,28 @@ EFI_STATUS storage_set_boot_device(EFI_HANDLE device) 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"Boot device is not PCI/SCSI, not supported"); + return EFI_UNSUPPORTED; + } + + error(L"Setting PCI 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); @@ -423,7 +538,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; } @@ -470,6 +584,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; }