4040
4141static struct storage * cur_storage ;
4242static PCI_DEVICE_PATH boot_device = { .Function = -1 , .Device = -1 };
43+ static SCSI_DEVICE_PATH boot_device_scsi = { .Pun = -1 , .Lun = -1 };
4344static enum storage_type boot_device_type ;
4445static BOOLEAN initialized = FALSE;
4546static 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);
6677extern struct storage STORAGE (STORAGE_SDCARD );
6778extern struct storage STORAGE (STORAGE_SATA );
6879extern struct storage STORAGE (STORAGE_NVME );
80+ extern struct storage STORAGE (STORAGE_ISCSI );
6981extern struct storage STORAGE (STORAGE_VIRTUAL );
7082#ifdef USB_STORAGE
7183extern 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+
146245EFI_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
242341static 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
310409EFI_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)
394494EFI_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