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

Commit 65183c4

Browse files
committed
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 <jianfeng.zhou@intel.com>
1 parent e4aafe0 commit 65183c4

6 files changed

Lines changed: 236 additions & 20 deletions

File tree

include/storage.h

100755100644
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ enum storage_type {
4343
STORAGE_SATA,
4444
STORAGE_NVME,
4545
STORAGE_VIRTUAL,
46+
STORAGE_ISCSI,
4647
#ifdef USB_STORAGE
4748
STORAGE_USB,
4849
#endif
@@ -94,4 +95,6 @@ EFI_STATUS set_logical_unit(UINT64 user_lun, UINT64 factory_lun);
9495
void print_progress(EFI_LBA done, EFI_LBA total, uint32_t sec, uint32_t *prev_sec, uint32_t *prev);
9596
void set_exclude_device(EFI_HANDLE device);
9697

98+
SCSI_DEVICE_PATH* get_scsi_device_path(EFI_DEVICE_PATH *p);
99+
97100
#endif /* _STORAGE_H_ */

libfastboot/fastboot_oem.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,10 @@ static void cmd_oem_set_storage(INTN argc, CHAR8 **argv)
338338
types[total_types++] = STORAGE_NVME;
339339
continue;
340340
}
341+
if (!strcmp(argv[i], (CHAR8 *)"iscsi")) {
342+
types[total_types++] = STORAGE_ISCSI;
343+
continue;
344+
}
341345
if (!strcmp(argv[i], (CHAR8 *)"sdcard")) {
342346
types[total_types++] = STORAGE_SDCARD;
343347
continue;

libkernelflinger/Android.mk

100755100644
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ LOCAL_SRC_FILES := \
123123
qsort.c \
124124
timer.c \
125125
nvme.c \
126+
iscsi.c \
126127
virtual_media.c \
127128
general_block.c \
128129
aes_gcm.c \

libkernelflinger/android.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,17 +1063,27 @@ static EFI_STATUS setup_command_line(
10631063
PCI_DEVICE_PATH *boot_device = get_boot_device();
10641064
if (boot_device) {
10651065
CHAR16 *diskbus = NULL;
1066+
enum storage_type storage_type;
10661067
#ifdef AUTO_DISKBUS
10671068
diskbus = PoolPrint(L"%02x.%x", boot_device->Device, boot_device->Function);
10681069
#else
10691070
diskbus = PoolPrint(L"%a", (CHAR8 *)PREDEF_DISK_BUS);
10701071
#endif
10711072
StrToLower(diskbus);
1072-
ret = prepend_command_line(&cmdline16,
1073-
(aosp_header->header_version < 2)
1074-
? L"androidboot.diskbus=%s"
1075-
: L"androidboot.boot_devices=pci0000:00/0000:00:%s",
1076-
diskbus);
1073+
1074+
get_boot_device_type(&storage_type);
1075+
if(aosp_header->header_version < 2)
1076+
ret = prepend_command_line(&cmdline16,
1077+
L"androidboot.diskbus=%s",
1078+
diskbus);
1079+
else
1080+
if(storage_type == STORAGE_ISCSI)
1081+
ret = prepend_command_line(&cmdline16,
1082+
L"androidboot.boot_devices=scsi_disk/0:0:0:0");
1083+
else
1084+
ret = prepend_command_line(&cmdline16,
1085+
L"androidboot.boot_devices=pci0000:00/0000:00:%s",
1086+
diskbus);
10771087
FreePool(diskbus);
10781088
if (EFI_ERROR(ret))
10791089
goto out;

libkernelflinger/iscsi.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright (c) 2020, Intel Corporation
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met:
8+
*
9+
* * Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
* * Redistributions in binary form must reproduce the above copyright
12+
* notice, this list of conditions and the following disclaimer
13+
* in the documentation and/or other materials provided with the
14+
* distribution.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20+
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25+
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
27+
* OF THE POSSIBILITY OF SUCH DAMAGE.
28+
*
29+
* This file defines bootlogic data structures, try to keep it without
30+
* any external definitions in order to ease export of it.
31+
*/
32+
33+
#include <lib.h>
34+
#include "storage.h"
35+
36+
#include "protocol/NvmExpressHci.h"
37+
#include "protocol/DevicePath.h"
38+
#include "protocol/NvmExpressPassthru.h"
39+
40+
#define ATTR_UNUSED __attribute__((unused))
41+
42+
#define MSG_SCSI_DP 0x02
43+
44+
#include "pci.h"
45+
46+
SCSI_DEVICE_PATH* get_scsi_device_path(EFI_DEVICE_PATH *p)
47+
{
48+
if (!p)
49+
return NULL;
50+
51+
while (!IsDevicePathEndType(p)) {
52+
if (DevicePathType(p) == MESSAGING_DEVICE_PATH
53+
&& DevicePathSubType(p) == MSG_SCSI_DP)
54+
return (SCSI_DEVICE_PATH *)p;
55+
p = NextDevicePathNode(p);
56+
}
57+
return NULL;
58+
}
59+
60+
static EFI_STATUS iscsi_erase_blocks(
61+
EFI_HANDLE handle ATTR_UNUSED,
62+
EFI_BLOCK_IO *bio ATTR_UNUSED,
63+
EFI_LBA start ATTR_UNUSED,
64+
EFI_LBA end ATTR_UNUSED
65+
)
66+
{
67+
return EFI_UNSUPPORTED;
68+
}
69+
70+
static EFI_STATUS iscsi_check_logical_unit(ATTR_UNUSED EFI_DEVICE_PATH *p, ATTR_UNUSED logical_unit_t log_unit)
71+
{
72+
return log_unit == LOGICAL_UNIT_USER ? EFI_SUCCESS : EFI_UNSUPPORTED;
73+
}
74+
75+
static BOOLEAN is_iscsi(EFI_DEVICE_PATH *p)
76+
{
77+
return get_scsi_device_path(p) != NULL;
78+
}
79+
80+
struct storage STORAGE(STORAGE_ISCSI) = {
81+
.erase_blocks = iscsi_erase_blocks,
82+
.check_logical_unit = iscsi_check_logical_unit,
83+
.probe = is_iscsi,
84+
.name = L"ISCSI"
85+
};
86+

libkernelflinger/storage.c

Lines changed: 127 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040

4141
static struct storage *cur_storage;
4242
static PCI_DEVICE_PATH boot_device = { .Function = -1, .Device = -1 };
43+
static SCSI_DEVICE_PATH boot_device_scsi = { .Pun = -1, .Lun = -1 };
4344
static enum storage_type boot_device_type;
4445
static BOOLEAN initialized = FALSE;
4546
static EFI_DEVICE_PATH *exclude_device = NULL;
@@ -52,10 +53,20 @@ static BOOLEAN is_boot_device(EFI_DEVICE_PATH *p)
5253
{
5354
PCI_DEVICE_PATH *pci;
5455

55-
if (boot_device.Header.Type == 0)
56+
if (boot_device.Header.Type == 0 && boot_device_scsi.Header.Type == 0)
5657
return FALSE;
5758

5859
pci = get_pci_device_path(p);
60+
if(pci == NULL)
61+
{
62+
SCSI_DEVICE_PATH *scsi = get_scsi_device_path(p);
63+
if(scsi == NULL) {
64+
debug(L"is_boot_device: not PCI/SCSI\n");
65+
return 0;
66+
}
67+
68+
return scsi->Pun == boot_device_scsi.Pun && scsi->Lun == boot_device_scsi.Lun;
69+
}
5970

6071
return pci && pci->Function == boot_device.Function
6172
&& pci->Device == boot_device.Device;
@@ -66,6 +77,7 @@ extern struct storage STORAGE(STORAGE_UFS);
6677
extern struct storage STORAGE(STORAGE_SDCARD);
6778
extern struct storage STORAGE(STORAGE_SATA);
6879
extern struct storage STORAGE(STORAGE_NVME);
80+
extern struct storage STORAGE(STORAGE_ISCSI);
6981
extern struct storage STORAGE(STORAGE_VIRTUAL);
7082
#ifdef USB_STORAGE
7183
extern struct storage STORAGE(STORAGE_USB);
@@ -86,6 +98,7 @@ static EFI_STATUS identify_storage(EFI_DEVICE_PATH *device_path,
8698
, &STORAGE(STORAGE_SATA)
8799
, &STORAGE(STORAGE_NVME)
88100
, &STORAGE(STORAGE_VIRTUAL)
101+
, &STORAGE(STORAGE_ISCSI)
89102
#ifdef USB_STORAGE
90103
, &STORAGE(STORAGE_USB)
91104
#endif
@@ -143,6 +156,92 @@ BOOLEAN is_same_device(EFI_DEVICE_PATH *p, EFI_DEVICE_PATH *e)
143156
return TRUE;
144157
}
145158

159+
EFI_STATUS identify_scsi_boot_device(enum storage_type filter)
160+
{
161+
EFI_STATUS ret;
162+
EFI_HANDLE *handles;
163+
UINTN nb_handle = 0;
164+
UINTN i;
165+
EFI_DEVICE_PATH *device_path;
166+
SCSI_DEVICE_PATH *scsi = NULL;
167+
struct storage *storage;
168+
enum storage_type type;
169+
EFI_HANDLE new_boot_device_handle = NULL;
170+
SCSI_DEVICE_PATH new_boot_device = { .Pun = -1, .Lun = -1 };
171+
enum storage_type new_boot_device_type;
172+
struct storage *new_storage;
173+
174+
new_storage = NULL;
175+
ret = uefi_call_wrapper(BS->LocateHandleBuffer, 5, ByProtocol,
176+
&BlockIoProtocol, NULL, &nb_handle, &handles);
177+
if (EFI_ERROR(ret)) {
178+
efi_perror(ret, L"Failed to locate Block IO Protocol");
179+
return ret;
180+
}
181+
182+
new_boot_device.Header.Type = 0;
183+
for (i = 0; i < nb_handle; i++) {
184+
device_path = DevicePathFromHandle(handles[i]);
185+
if (!device_path)
186+
continue;
187+
188+
scsi = get_scsi_device_path(device_path);
189+
if (!scsi)
190+
continue;
191+
192+
if (is_same_device(device_path, exclude_device))
193+
continue;
194+
195+
if (new_boot_device.Pun == scsi->Pun &&
196+
new_boot_device.Lun == scsi->Lun &&
197+
new_boot_device.Header.Type == scsi->Header.Type &&
198+
new_boot_device.Header.SubType == scsi->Header.SubType)
199+
continue;
200+
201+
ret = identify_storage(device_path, filter, &storage, &type);
202+
if (EFI_ERROR(ret))
203+
continue;
204+
205+
if (!new_boot_device.Header.Type || new_boot_device_type >= type) {
206+
ret = memcpy_s(&new_boot_device, sizeof(new_boot_device), scsi,
207+
sizeof(new_boot_device));
208+
if (EFI_ERROR(ret)) {
209+
FreePool(handles);
210+
return ret;
211+
}
212+
new_boot_device_type = type;
213+
new_storage = storage;
214+
new_boot_device_handle = handles[i];
215+
continue;
216+
}
217+
218+
if (new_boot_device_type == type &&
219+
type != STORAGE_GENERAL_BLOCK &&
220+
filter > type) {
221+
error(L"Multiple identifcal storage found! Can't make a decision");
222+
new_storage = NULL;
223+
new_boot_device.Header.Type = 0;
224+
FreePool(handles);
225+
return EFI_UNSUPPORTED;
226+
}
227+
}
228+
229+
FreePool(handles);
230+
231+
if (!new_storage) {
232+
error(L"No SCSI storage found for type %d", filter);
233+
return EFI_UNSUPPORTED;
234+
}
235+
cur_storage = new_storage;
236+
boot_device_type = new_boot_device_type;
237+
boot_device_handle = new_boot_device_handle;
238+
boot_device_scsi = new_boot_device;
239+
240+
debug(L"%s storage selected", cur_storage->name);
241+
return EFI_SUCCESS;
242+
}
243+
244+
146245
EFI_STATUS identify_boot_device(enum storage_type filter)
147246
{
148247
EFI_STATUS ret;
@@ -216,8 +315,7 @@ EFI_STATUS identify_boot_device(enum storage_type filter)
216315
FreePool(handles);
217316

218317
if (!new_storage) {
219-
error(L"No PCI storage found for type %d", filter);
220-
return EFI_UNSUPPORTED;
318+
return identify_scsi_boot_device(filter);
221319
}
222320
cur_storage = new_storage;
223321
boot_device_type = new_boot_device_type;
@@ -236,7 +334,8 @@ static BOOLEAN valid_storage(void)
236334
initialized = TRUE;
237335
return !EFI_ERROR(identify_boot_device(STORAGE_ALL));
238336
}
239-
return boot_device.Header.Type && cur_storage;
337+
338+
return (boot_device.Header.Type || boot_device_scsi.Header.Type) && cur_storage;
240339
}
241340

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

310409
EFI_STATUS storage_check_logical_unit(EFI_DEVICE_PATH *p, logical_unit_t log_unit)
311410
{
312-
if (!valid_storage())
411+
if (!valid_storage()) {
313412
return EFI_UNSUPPORTED;
314-
if (!is_boot_device(p))
413+
}
414+
if (!is_boot_device(p)) {
315415
return EFI_UNSUPPORTED;
316-
416+
}
317417
return cur_storage->check_logical_unit(p, log_unit);
318418
}
319419

@@ -394,27 +494,37 @@ EFI_STATUS fill_zero(EFI_BLOCK_IO *bio, EFI_LBA start, EFI_LBA end)
394494
EFI_STATUS storage_set_boot_device(EFI_HANDLE device)
395495
{
396496
EFI_DEVICE_PATH *device_path = DevicePathFromHandle(device);
397-
PCI_DEVICE_PATH *pci;
398497
EFI_STATUS ret;
498+
PCI_DEVICE_PATH *pci;
399499
CHAR16 *dps;
400500

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

406-
pci = get_pci_device_path(device_path);
407-
if (!pci) {
408-
error(L"Boot device is not PCI, unsupported");
409-
return EFI_UNSUPPORTED;
410-
}
411-
412506
ret = identify_storage(device_path, STORAGE_ALL, &cur_storage,
413507
&boot_device_type);
414508
if (EFI_ERROR(ret)) {
415509
error(L"Boot device unsupported");
416510
return ret;
417511
}
512+
513+
pci = get_pci_device_path(device_path);
514+
if (!pci) {
515+
SCSI_DEVICE_PATH *scsi = get_scsi_device_path(device_path);
516+
if(scsi == NULL) {
517+
error(L"Only PCI/SCSI boot device is supported");
518+
return EFI_UNSUPPORTED;
519+
}
520+
521+
error(L"Setting boot device to: SCSI");
522+
initialized = TRUE;
523+
boot_device_scsi = *scsi;
524+
boot_device_handle = device;
525+
return EFI_SUCCESS;
526+
}
527+
418528
dps = DevicePathToStr((EFI_DEVICE_PATH *)pci);
419529
debug(L"Setting PCI boot device to: %s", dps);
420530
FreePool(dps);
@@ -423,7 +533,6 @@ EFI_STATUS storage_set_boot_device(EFI_HANDLE device)
423533
ret = memcpy_s(&boot_device, sizeof(boot_device), pci, sizeof(boot_device));
424534
if (EFI_ERROR(ret))
425535
return ret;
426-
427536
boot_device_handle = device;
428537
return EFI_SUCCESS;
429538
}
@@ -470,6 +579,9 @@ PCI_DEVICE_PATH *get_boot_device(void)
470579
else
471580
initialized = TRUE;
472581
}
582+
583+
if(boot_device_scsi.Header.Type)
584+
return (PCI_DEVICE_PATH *)&boot_device_scsi;
473585
return boot_device.Header.Type == 0 ? NULL : &boot_device;
474586
}
475587

0 commit comments

Comments
 (0)