iPXE
sanboot.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2017 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27/**
28 * @file
29 *
30 * SAN booting
31 *
32 */
33
34#include <stdint.h>
35#include <stdlib.h>
36#include <string.h>
37#include <errno.h>
38#include <assert.h>
39#include <ipxe/xfer.h>
40#include <ipxe/open.h>
41#include <ipxe/timer.h>
42#include <ipxe/process.h>
43#include <ipxe/iso9660.h>
44#include <ipxe/dhcp.h>
45#include <ipxe/settings.h>
46#include <ipxe/quiesce.h>
47#include <ipxe/sanboot.h>
48
49/**
50 * Timeout for block device commands (in ticks)
51 *
52 * Underlying devices should ideally never become totally stuck.
53 * However, if they do, then the blocking SAN APIs provide no means
54 * for the caller to cancel the operation, and the machine appears to
55 * hang. Use an overall timeout for all commands to avoid this
56 * problem and bounce timeout failures to the caller.
57 */
58#define SAN_COMMAND_TIMEOUT ( 15 * TICKS_PER_SEC )
59
60/**
61 * Default number of times to retry commands
62 *
63 * We may need to retry commands. For example, the underlying
64 * connection may be closed by the SAN target due to an inactivity
65 * timeout, or the SAN target may return pointless "error" messages
66 * such as "SCSI power-on occurred".
67 */
68#define SAN_DEFAULT_RETRIES 10
69
70/**
71 * Delay between reopening attempts
72 *
73 * Some SAN targets will always accept connections instantly and
74 * report a temporary unavailability by e.g. failing the TEST UNIT
75 * READY command. Avoid bombarding such targets by introducing a
76 * small delay between attempts.
77 */
78#define SAN_REOPEN_DELAY_SECS 5
79
80/** List of SAN devices */
82
83/** Number of times to retry commands */
84static unsigned long san_retries = SAN_DEFAULT_RETRIES;
85
86/**
87 * Find SAN device by drive number
88 *
89 * @v drive Drive number
90 * @ret sandev SAN device, or NULL
91 */
92struct san_device * sandev_find ( unsigned int drive ) {
93 struct san_device *sandev;
94
96 if ( sandev->drive == drive )
97 return sandev;
98 }
99 return NULL;
100}
101
102/**
103 * Find next SAN device by drive number
104 *
105 * @v drive Minimum drive number
106 * @ret sandev SAN device, or NULL
107 */
108struct san_device * sandev_next ( unsigned int drive ) {
109 struct san_device *sandev;
110
111 list_for_each_entry ( sandev, &san_devices, list ) {
112 if ( sandev->drive >= drive )
113 return sandev;
114 }
115 return NULL;
116}
117
118/**
119 * Free SAN device
120 *
121 * @v refcnt Reference count
122 */
123static void sandev_free ( struct refcnt *refcnt ) {
124 struct san_device *sandev =
126 unsigned int i;
127
128 assert ( ! timer_running ( &sandev->timer ) );
129 assert ( ! sandev->active );
130 assert ( list_empty ( &sandev->opened ) );
131 for ( i = 0 ; i < sandev->paths ; i++ ) {
132 uri_put ( sandev->path[i].uri );
133 assert ( sandev->path[i].desc == NULL );
134 }
135 free ( sandev );
136}
137
138/**
139 * Close SAN device command
140 *
141 * @v sandev SAN device
142 * @v rc Reason for close
143 */
144static void sandev_command_close ( struct san_device *sandev, int rc ) {
145
146 /* Stop timer */
147 stop_timer ( &sandev->timer );
148
149 /* Restart interface */
150 intf_restart ( &sandev->command, rc );
151
152 /* Record command status */
153 sandev->command_rc = rc;
154}
155
156/**
157 * Record SAN device capacity
158 *
159 * @v sandev SAN device
160 * @v capacity SAN device capacity
161 */
162static void sandev_command_capacity ( struct san_device *sandev,
164
165 /* Record raw capacity information */
166 memcpy ( &sandev->capacity, capacity, sizeof ( sandev->capacity ) );
167}
168
169/** SAN device command interface operations */
175
176/** SAN device command interface descriptor */
179
180/**
181 * Handle SAN device command timeout
182 *
183 * @v retry Retry timer
184 */
186 int over __unused ) {
187 struct san_device *sandev =
188 container_of ( timer, struct san_device, timer );
189
190 sandev_command_close ( sandev, -ETIMEDOUT );
191}
192
193/**
194 * Open SAN path
195 *
196 * @v sanpath SAN path
197 * @ret rc Return status code
198 */
199static int sanpath_open ( struct san_path *sanpath ) {
200 struct san_device *sandev = sanpath->sandev;
201 int rc;
202
203 /* Sanity check */
204 list_check_contains_entry ( sanpath, &sandev->closed, list );
205
206 /* Open interface */
207 if ( ( rc = xfer_open_uri ( &sanpath->block, sanpath->uri ) ) != 0 ) {
208 DBGC ( sandev->drive, "SAN %#02x.%d could not (re)open URI: "
209 "%s\n", sandev->drive, sanpath->index, strerror ( rc ) );
210 return rc;
211 }
212
213 /* Update ACPI descriptor, if applicable */
214 if ( ! ( sandev->flags & SAN_NO_DESCRIBE ) ) {
215 if ( sanpath->desc )
216 acpi_del ( sanpath->desc );
217 sanpath->desc = acpi_describe ( &sanpath->block );
218 if ( sanpath->desc )
219 acpi_add ( sanpath->desc );
220 }
221
222 /* Start process */
223 process_add ( &sanpath->process );
224
225 /* Mark as opened */
226 list_del ( &sanpath->list );
227 list_add_tail ( &sanpath->list, &sandev->opened );
228
229 /* Record as in progress */
230 sanpath->path_rc = -EINPROGRESS;
231
232 return 0;
233}
234
235/**
236 * Close SAN path
237 *
238 * @v sanpath SAN path
239 * @v rc Reason for close
240 */
241static void sanpath_close ( struct san_path *sanpath, int rc ) {
242 struct san_device *sandev = sanpath->sandev;
243
244 /* Record status */
245 sanpath->path_rc = rc;
246
247 /* Mark as closed */
248 list_del ( &sanpath->list );
249 list_add_tail ( &sanpath->list, &sandev->closed );
250
251 /* Stop process */
252 process_del ( &sanpath->process );
253
254 /* Restart interfaces, avoiding potential loops */
255 if ( sanpath == sandev->active ) {
256 intfs_restart ( rc, &sandev->command, &sanpath->block, NULL );
257 sandev->active = NULL;
258 sandev_command_close ( sandev, rc );
259 } else {
260 intf_restart ( &sanpath->block, rc );
261 }
262}
263
264/**
265 * Handle closure of underlying block device interface
266 *
267 * @v sanpath SAN path
268 * @v rc Reason for close
269 */
270static void sanpath_block_close ( struct san_path *sanpath, int rc ) {
271 struct san_device *sandev = sanpath->sandev;
272
273 /* Any closure is an error from our point of view */
274 if ( rc == 0 )
275 rc = -ENOTCONN;
276 DBGC ( sandev->drive, "SAN %#02x.%d closed: %s\n",
277 sandev->drive, sanpath->index, strerror ( rc ) );
278
279 /* Close path */
280 sanpath_close ( sanpath, rc );
281}
282
283/**
284 * Check flow control window
285 *
286 * @v sanpath SAN path
287 */
288static size_t sanpath_block_window ( struct san_path *sanpath __unused ) {
289
290 /* We are never ready to receive data via this interface.
291 * This prevents objects that support both block and stream
292 * interfaces from attempting to send us stream data.
293 */
294 return 0;
295}
296
297/**
298 * SAN path process
299 *
300 * @v sanpath SAN path
301 */
302static void sanpath_step ( struct san_path *sanpath ) {
303 struct san_device *sandev = sanpath->sandev;
304
305 /* Ignore if we are already the active device */
306 if ( sanpath == sandev->active )
307 return;
308
309 /* Wait until path has become available */
310 if ( ! xfer_window ( &sanpath->block ) )
311 return;
312
313 /* Record status */
314 sanpath->path_rc = 0;
315
316 /* Mark as active path or close as applicable */
317 if ( ! sandev->active ) {
318 DBGC ( sandev->drive, "SAN %#02x.%d is active\n",
319 sandev->drive, sanpath->index );
320 sandev->active = sanpath;
321 } else {
322 DBGC ( sandev->drive, "SAN %#02x.%d is available\n",
323 sandev->drive, sanpath->index );
324 sanpath_close ( sanpath, 0 );
325 }
326}
327
328/** SAN path block interface operations */
334
335/** SAN path block interface descriptor */
338
339/** SAN path process descriptor */
342
343/**
344 * Restart SAN device interface
345 *
346 * @v sandev SAN device
347 * @v rc Reason for restart
348 */
349static void sandev_restart ( struct san_device *sandev, int rc ) {
350 struct san_path *sanpath;
351
352 /* Restart all block device interfaces */
353 while ( ( sanpath = list_first_entry ( &sandev->opened,
354 struct san_path, list ) ) ) {
355 sanpath_close ( sanpath, rc );
356 }
357
358 /* Clear active path */
359 sandev->active = NULL;
360
361 /* Close any outstanding command */
363}
364
365/**
366 * (Re)open SAN device
367 *
368 * @v sandev SAN device
369 * @ret rc Return status code
370 *
371 * This function will block until the device is available.
372 */
374 struct san_path *sanpath;
375 int rc;
376
377 /* Unquiesce system */
378 unquiesce();
379
380 /* Close any outstanding command and restart interfaces */
382 assert ( sandev->active == NULL );
383 assert ( list_empty ( &sandev->opened ) );
384
385 /* Open all paths */
386 while ( ( sanpath = list_first_entry ( &sandev->closed,
387 struct san_path, list ) ) ) {
388 if ( ( rc = sanpath_open ( sanpath ) ) != 0 )
389 goto err_open;
390 }
391
392 /* Wait for any device to become available, or for all devices
393 * to fail.
394 */
395 while ( sandev->active == NULL ) {
396 step();
397 if ( list_empty ( &sandev->opened ) ) {
398 /* Get status of the first device to be
399 * closed. Do this on the basis that earlier
400 * errors (e.g. "invalid IQN") are probably
401 * more interesting than later errors
402 * (e.g. "TCP timeout").
403 */
404 rc = -ENODEV;
405 list_for_each_entry ( sanpath, &sandev->closed, list ) {
406 rc = sanpath->path_rc;
407 break;
408 }
409 DBGC ( sandev->drive, "SAN %#02x never became "
410 "available: %s\n", sandev->drive,
411 strerror ( rc ) );
412 goto err_none;
413 }
414 }
415
416 assert ( ! list_empty ( &sandev->opened ) );
417 return 0;
418
419 err_none:
420 err_open:
422 return rc;
423}
424
425/** SAN device read/write command parameters */
427 /** SAN device read/write operation */
428 int ( * block_rw ) ( struct interface *control, struct interface *data,
429 uint64_t lba, unsigned int count, void *buffer,
430 size_t len );
431 /** Data buffer */
432 void *buffer;
433 /** Starting LBA */
435 /** Block count */
436 unsigned int count;
437};
438
439/** SAN device command parameters */
441 /** Read/write command parameters */
443};
444
445/**
446 * Initiate SAN device read/write command
447 *
448 * @v sandev SAN device
449 * @v params Command parameters
450 * @ret rc Return status code
451 */
452static int sandev_command_rw ( struct san_device *sandev,
453 const union san_command_params *params ) {
454 struct san_path *sanpath = sandev->active;
455 size_t len = ( params->rw.count * sandev->capacity.blksize );
456 int rc;
457
458 /* Sanity check */
459 assert ( sanpath != NULL );
460
461 /* Initiate read/write command */
462 if ( ( rc = params->rw.block_rw ( &sanpath->block, &sandev->command,
463 params->rw.lba, params->rw.count,
464 params->rw.buffer, len ) ) != 0 ) {
465 DBGC ( sandev->drive, "SAN %#02x.%d could not initiate "
466 "read/write: %s\n", sandev->drive, sanpath->index,
467 strerror ( rc ) );
468 return rc;
469 }
470
471 return 0;
472}
473
474/**
475 * Initiate SAN device read capacity command
476 *
477 * @v sandev SAN device
478 * @v params Command parameters
479 * @ret rc Return status code
480 */
481static int
483 const union san_command_params *params __unused){
484 struct san_path *sanpath = sandev->active;
485 int rc;
486
487 /* Sanity check */
488 assert ( sanpath != NULL );
489
490 /* Initiate read capacity command */
491 if ( ( rc = block_read_capacity ( &sanpath->block,
492 &sandev->command ) ) != 0 ) {
493 DBGC ( sandev->drive, "SAN %#02x.%d could not initiate read "
494 "capacity: %s\n", sandev->drive, sanpath->index,
495 strerror ( rc ) );
496 return rc;
497 }
498
499 return 0;
500}
501
502/**
503 * Execute a single SAN device command and wait for completion
504 *
505 * @v sandev SAN device
506 * @v command Command
507 * @v params Command parameters (if required)
508 * @ret rc Return status code
509 */
510static int
512 int ( * command ) ( struct san_device *sandev,
513 const union san_command_params *params ),
514 const union san_command_params *params ) {
515 unsigned int retries = 0;
516 int rc;
517
518 /* Sanity check */
519 assert ( ! timer_running ( &sandev->timer ) );
520
521 /* Unquiesce system */
522 unquiesce();
523
524 /* (Re)try command */
525 do {
526
527 /* Reopen block device if applicable */
528 if ( sandev_needs_reopen ( sandev ) &&
529 ( ( rc = sandev_reopen ( sandev ) ) != 0 ) ) {
530
531 /* Delay reopening attempts */
533
534 /* Retry opening indefinitely for multipath devices */
535 if ( sandev->paths <= 1 )
536 retries++;
537
538 continue;
539 }
540
541 /* Initiate command */
542 if ( ( rc = command ( sandev, params ) ) != 0 ) {
543 retries++;
544 continue;
545 }
546
547 /* Start expiry timer */
549
550 /* Wait for command to complete */
551 while ( timer_running ( &sandev->timer ) )
552 step();
553
554 /* Check command status */
555 if ( ( rc = sandev->command_rc ) != 0 ) {
556 retries++;
557 continue;
558 }
559
560 return 0;
561
562 } while ( retries <= san_retries );
563
564 /* Sanity check */
565 assert ( ! timer_running ( &sandev->timer ) );
566
567 return rc;
568}
569
570/**
571 * Reset SAN device
572 *
573 * @v sandev SAN device
574 * @ret rc Return status code
575 */
577 int rc;
578
579 DBGC ( sandev->drive, "SAN %#02x reset\n", sandev->drive );
580
581 /* Close and reopen underlying block device */
582 if ( ( rc = sandev_reopen ( sandev ) ) != 0 )
583 return rc;
584
585 return 0;
586}
587
588/**
589 * Read from or write to SAN device
590 *
591 * @v sandev SAN device
592 * @v lba Starting logical block address
593 * @v count Number of logical blocks
594 * @v buffer Data buffer
595 * @v block_rw Block read/write method
596 * @ret rc Return status code
597 */
598static int sandev_rw ( struct san_device *sandev, uint64_t lba,
599 unsigned int count, void *buffer,
600 int ( * block_rw ) ( struct interface *control,
601 struct interface *data,
602 uint64_t lba, unsigned int count,
603 void *buffer, size_t len ) ) {
604 union san_command_params params;
605 unsigned int remaining;
606 size_t frag_len;
607 int rc;
608
609 /* Initialise command parameters */
610 params.rw.block_rw = block_rw;
611 params.rw.buffer = buffer;
612 params.rw.lba = ( lba << sandev->blksize_shift );
613 params.rw.count = sandev->capacity.max_count;
614 remaining = ( count << sandev->blksize_shift );
615
616 /* Read/write fragments */
617 while ( remaining ) {
618
619 /* Determine fragment length */
620 if ( params.rw.count > remaining )
621 params.rw.count = remaining;
622
623 /* Execute command */
624 if ( ( rc = sandev_command ( sandev, sandev_command_rw,
625 &params ) ) != 0 )
626 return rc;
627
628 /* Move to next fragment */
629 frag_len = ( sandev->capacity.blksize * params.rw.count );
630 params.rw.buffer += frag_len;
631 params.rw.lba += params.rw.count;
632 remaining -= params.rw.count;
633 }
634
635 return 0;
636}
637
638/**
639 * Read from SAN device
640 *
641 * @v sandev SAN device
642 * @v lba Starting logical block address
643 * @v count Number of logical blocks
644 * @v buffer Data buffer
645 * @ret rc Return status code
646 */
647int sandev_read ( struct san_device *sandev, uint64_t lba,
648 unsigned int count, void *buffer ) {
649 int rc;
650
651 /* Read from device */
652 if ( ( rc = sandev_rw ( sandev, lba, count, buffer,
653 block_read ) ) != 0 )
654 return rc;
655
656 return 0;
657}
658
659/**
660 * Write to SAN device
661 *
662 * @v sandev SAN device
663 * @v lba Starting logical block address
664 * @v count Number of logical blocks
665 * @v buffer Data buffer
666 * @ret rc Return status code
667 */
668int sandev_write ( struct san_device *sandev, uint64_t lba,
669 unsigned int count, void *buffer ) {
670 int rc;
671
672 /* Write to device */
673 if ( ( rc = sandev_rw ( sandev, lba, count, buffer,
674 block_write ) ) != 0 )
675 return rc;
676
677 /* Quiesce system. This is a heuristic designed to ensure
678 * that the system is quiesced before Windows starts up, since
679 * a Windows SAN boot will typically write a status flag to
680 * the disk as its last action before transferring control to
681 * the native drivers.
682 */
683 quiesce();
684
685 return 0;
686}
687
688/**
689 * Describe SAN device
690 *
691 * @v sandev SAN device
692 * @ret rc Return status code
693 *
694 * Allow connections to progress until all existent path descriptors
695 * are complete.
696 */
697static int sandev_describe ( struct san_device *sandev ) {
698 struct san_path *sanpath;
699 struct acpi_descriptor *desc;
700 int rc;
701
702 /* Wait for all paths to be either described or closed */
703 while ( 1 ) {
704
705 /* Allow connections to progress */
706 step();
707
708 /* Fail if any closed path has an incomplete descriptor */
709 list_for_each_entry ( sanpath, &sandev->closed, list ) {
710 desc = sanpath->desc;
711 if ( ! desc )
712 continue;
713 if ( ( rc = desc->model->complete ( desc ) ) != 0 ) {
714 DBGC ( sandev->drive, "SAN %#02x.%d could not "
715 "be described: %s\n", sandev->drive,
716 sanpath->index, strerror ( rc ) );
717 return rc;
718 }
719 }
720
721 /* Succeed if no paths have an incomplete descriptor */
722 rc = 0;
723 list_for_each_entry ( sanpath, &sandev->opened, list ) {
724 desc = sanpath->desc;
725 if ( ! desc )
726 continue;
727 if ( ( rc = desc->model->complete ( desc ) ) != 0 )
728 break;
729 }
730 if ( rc == 0 )
731 return 0;
732 }
733}
734
735/**
736 * Remove SAN device descriptors
737 *
738 * @v sandev SAN device
739 */
740static void sandev_undescribe ( struct san_device *sandev ) {
741 struct san_path *sanpath;
742 unsigned int i;
743
744 /* Remove all ACPI descriptors */
745 for ( i = 0 ; i < sandev->paths ; i++ ) {
746 sanpath = &sandev->path[i];
747 if ( sanpath->desc ) {
748 acpi_del ( sanpath->desc );
749 sanpath->desc = NULL;
750 }
751 }
752}
753
754/**
755 * Configure SAN device as a CD-ROM, if applicable
756 *
757 * @v sandev SAN device
758 * @ret rc Return status code
759 *
760 * Both BIOS and UEFI require SAN devices to be accessed with a block
761 * size of 2048. While we could require the user to configure the
762 * block size appropriately, this is non-trivial and would impose a
763 * substantial learning effort on the user. Instead, we check for the
764 * presence of the ISO9660 primary volume descriptor and, if found,
765 * then we force a block size of 2048 and map read/write requests
766 * appropriately.
767 */
768static int sandev_parse_iso9660 ( struct san_device *sandev ) {
769 static const struct iso9660_primary_descriptor_fixed primary_check = {
770 .type = ISO9660_TYPE_PRIMARY,
771 .id = ISO9660_ID,
772 };
773 union {
776 } *scratch;
777 unsigned int blksize;
778 unsigned int blksize_shift;
779 unsigned int lba;
780 unsigned int count;
781 int rc;
782
783 /* Calculate required blocksize shift for potential CD-ROM access */
784 blksize = sandev->capacity.blksize;
785 blksize_shift = 0;
786 while ( blksize < ISO9660_BLKSIZE ) {
787 blksize <<= 1;
788 blksize_shift++;
789 }
790 if ( blksize > ISO9660_BLKSIZE ) {
791 /* Cannot be a CD-ROM. This is not an error. */
792 rc = 0;
793 goto invalid_blksize;
794 }
795 lba = ( ISO9660_PRIMARY_LBA << blksize_shift );
796 count = ( 1 << blksize_shift );
797
798 /* Allocate scratch area */
799 scratch = malloc ( ISO9660_BLKSIZE );
800 if ( ! scratch ) {
801 rc = -ENOMEM;
802 goto err_alloc;
803 }
804
805 /* Read primary volume descriptor */
806 if ( ( rc = sandev_read ( sandev, lba, count, scratch ) ) != 0 ) {
807 DBGC ( sandev->drive, "SAN %#02x could not read ISO9660 "
808 "primary volume descriptor: %s\n",
809 sandev->drive, strerror ( rc ) );
810 goto err_rw;
811 }
812
813 /* Configure as CD-ROM if applicable */
814 if ( memcmp ( &scratch->primary.fixed, &primary_check,
815 sizeof ( primary_check ) ) == 0 ) {
816 DBGC ( sandev->drive, "SAN %#02x contains an ISO9660 "
817 "filesystem; treating as CD-ROM\n", sandev->drive );
818 sandev->blksize_shift = blksize_shift;
819 sandev->is_cdrom = 1;
820 }
821
822 err_rw:
823 free ( scratch );
824 err_alloc:
825 invalid_blksize:
826 return rc;
827}
828
829/**
830 * Allocate SAN device
831 *
832 * @v uris List of URIs
833 * @v count Number of URIs
834 * @v priv_size Size of private data
835 * @ret sandev SAN device, or NULL
836 */
837struct san_device * alloc_sandev ( struct uri **uris, unsigned int count,
838 size_t priv_size ) {
839 struct san_device *sandev;
840 struct san_path *sanpath;
841 size_t size;
842 unsigned int i;
843
844 /* Allocate and initialise structure */
845 size = ( sizeof ( *sandev ) + ( count * sizeof ( sandev->path[0] ) ) );
846 sandev = zalloc ( size + priv_size );
847 if ( ! sandev )
848 return NULL;
851 timer_init ( &sandev->timer, sandev_command_expired, &sandev->refcnt );
852 sandev->priv = ( ( ( void * ) sandev ) + size );
853 sandev->paths = count;
856 for ( i = 0 ; i < count ; i++ ) {
857 sanpath = &sandev->path[i];
858 sanpath->sandev = sandev;
859 sanpath->index = i;
860 sanpath->uri = uri_get ( uris[i] );
861 list_add_tail ( &sanpath->list, &sandev->closed );
862 intf_init ( &sanpath->block, &sanpath_block_desc,
863 &sandev->refcnt );
865 &sandev->refcnt );
866 sanpath->path_rc = -EINPROGRESS;
867 }
868
869 return sandev;
870}
871
872/**
873 * Register SAN device
874 *
875 * @v sandev SAN device
876 * @v drive Drive number
877 * @v flags Flags
878 * @ret rc Return status code
879 */
880int register_sandev ( struct san_device *sandev, unsigned int drive,
881 unsigned int flags ) {
882 struct san_device *before;
883 int rc;
884
885 /* Check that drive number is not in use */
886 if ( sandev_find ( drive ) != NULL ) {
887 DBGC ( sandev->drive, "SAN %#02x is already in use\n", drive );
888 rc = -EADDRINUSE;
889 goto err_in_use;
890 }
891
892 /* Record drive number and flags */
893 sandev->drive = drive;
894 sandev->flags = flags;
895
896 /* Check that device is capable of being opened (i.e. that all
897 * URIs are well-formed and that at least one path is
898 * working).
899 */
900 if ( ( rc = sandev_reopen ( sandev ) ) != 0 )
901 goto err_reopen;
902
903 /* Describe device */
904 if ( ( rc = sandev_describe ( sandev ) ) != 0 )
905 goto err_describe;
906
907 /* Read device capacity */
909 NULL ) ) != 0 )
910 goto err_capacity;
911
912 /* Configure as a CD-ROM, if applicable */
913 if ( ( rc = sandev_parse_iso9660 ( sandev ) ) != 0 )
914 goto err_iso9660;
915
916 /* Add to list of SAN devices, in drive order */
918 if ( before->drive > sandev->drive )
919 break;
920 }
921 list_add_tail ( &sandev->list, &before->list );
922 DBGC ( sandev->drive, "SAN %#02x registered\n", sandev->drive );
923
924 return 0;
925
926 list_del ( &sandev->list );
927 err_iso9660:
928 err_capacity:
929 err_describe:
930 err_reopen:
931 sandev_restart ( sandev, rc );
932 sandev_undescribe ( sandev );
933 err_in_use:
934 return rc;
935}
936
937/**
938 * Unregister SAN device
939 *
940 * @v sandev SAN device
941 */
942void unregister_sandev ( struct san_device *sandev ) {
943
944 /* Sanity check */
945 assert ( ! timer_running ( &sandev->timer ) );
946
947 /* Remove from list of SAN devices */
948 list_del ( &sandev->list );
949
950 /* Shut down interfaces */
951 sandev_restart ( sandev, 0 );
952
953 /* Remove ACPI descriptors */
954 sandev_undescribe ( sandev );
955
956 DBGC ( sandev->drive, "SAN %#02x unregistered\n", sandev->drive );
957}
958
959/** The "san-drive" setting */
960const struct setting san_drive_setting __setting ( SETTING_SANBOOT_EXTRA,
961 san-drive ) = {
962 .name = "san-drive",
963 .description = "SAN drive number",
964 .tag = DHCP_EB_SAN_DRIVE,
965 .type = &setting_type_uint8,
966};
967
968/**
969 * Get default SAN drive number
970 *
971 * @ret drive Default drive number
972 */
973unsigned int san_default_drive ( void ) {
974 unsigned long drive;
975
976 /* Use "san-drive" setting, if specified */
977 if ( fetch_uint_setting ( NULL, &san_drive_setting, &drive ) >= 0 )
978 return drive;
979
980 /* Otherwise, default to booting from first hard disk */
981 return SAN_DEFAULT_DRIVE;
982}
983
984/** The "san-retries" setting */
985const struct setting san_retries_setting __setting ( SETTING_SANBOOT_EXTRA,
986 san-retries ) = {
987 .name = "san-retries",
988 .description = "SAN retry count",
989 .tag = DHCP_EB_SAN_RETRY,
990 .type = &setting_type_int8,
991};
992
993/**
994 * Apply SAN boot settings
995 *
996 * @ret rc Return status code
997 */
998static int sandev_apply ( void ) {
999
1000 /* Apply "san-retries" setting */
1001 if ( fetch_uint_setting ( NULL, &san_retries_setting,
1002 &san_retries ) < 0 ) {
1004 }
1005
1006 return 0;
1007}
1008
1009/** Settings applicator */
1010struct settings_applicator sandev_applicator __settings_applicator = {
1011 .apply = sandev_apply,
1012};
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
void acpi_del(struct acpi_descriptor *desc)
Remove ACPI descriptor.
Definition acpi.c:307
void acpi_add(struct acpi_descriptor *desc)
Add ACPI descriptor.
Definition acpi.c:295
struct acpi_descriptor * acpi_describe(struct interface *intf)
Get object's ACPI descriptor.
Definition acpi.c:321
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned long long uint64_t
Definition stdint.h:13
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
int block_read_capacity(struct interface *control, struct interface *data)
Read block device capacity.
Definition blockdev.c:106
int block_write(struct interface *control, struct interface *data, uint64_t lba, unsigned int count, void *buffer, size_t len)
Write to block device.
Definition blockdev.c:79
int block_read(struct interface *control, struct interface *data, uint64_t lba, unsigned int count, void *buffer, size_t len)
Read from block device.
Definition blockdev.c:48
void block_capacity(struct interface *intf, struct block_device_capacity *capacity)
Report block device capacity.
Definition blockdev.c:130
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint8_t flags
Flags.
Definition ena.h:7
struct ena_llq_option desc
Descriptor counts.
Definition ena.h:9
Error codes.
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define DBGC(...)
Definition compiler.h:505
#define DHCP_EB_SAN_DRIVE
SAN drive number.
Definition dhcp.h:479
#define DHCP_EB_SAN_RETRY
SAN retry count.
Definition dhcp.h:466
uint8_t drive
Drive number.
Definition int13.h:5
uint16_t size
Buffer size.
Definition dwmac.h:3
static unsigned int count
Number of entries.
Definition dwmac.h:220
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER)
Definition netvsc.h:5
uint64_t lba
Starting block number.
Definition int13.h:11
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ETIMEDOUT
Connection timed out.
Definition errno.h:670
#define EADDRINUSE
Address already in use.
Definition errno.h:304
#define ENOMEM
Not enough space.
Definition errno.h:535
#define EINPROGRESS
Operation in progress.
Definition errno.h:419
#define ENODEV
No such device.
Definition errno.h:510
#define ECONNRESET
Connection reset.
Definition errno.h:364
#define ENOTCONN
The socket is not connected.
Definition errno.h:570
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define SETTING_SANBOOT_EXTRA
SAN boot additional settings.
Definition settings.h:75
struct ib_cm_path primary
Primary path.
Definition ib_mad.h:29
uint8_t bytes[64]
Definition ib_mad.h:5
Dynamic Host Configuration Protocol.
iPXE sanboot API
@ SAN_NO_DESCRIBE
Device should not be included in description tables.
Definition sanboot.h:107
static int sandev_needs_reopen(struct san_device *sandev)
Check if SAN device needs to be reopened.
Definition sanboot.h:256
#define SAN_DEFAULT_DRIVE
Default SAN drive number.
Definition sanboot.h:34
struct list_head san_devices
#define for_each_sandev(sandev)
Iterate over all SAN devices.
Definition sanboot.h:197
Configuration settings.
#define __setting(setting_order, name)
Declare a configuration setting.
Definition settings.h:57
#define __settings_applicator
Declare a settings applicator.
Definition settings.h:265
iPXE timers
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void intfs_restart(int rc,...)
Shut down and restart multiple object interfaces.
Definition interface.c:387
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition interface.c:344
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition interface.h:81
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition interface.h:204
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
ISO9660 CD-ROM specification.
#define ISO9660_BLKSIZE
ISO9660 block size.
Definition iso9660.h:17
#define ISO9660_TYPE_PRIMARY
ISO9660 Primary Volume Descriptor type.
Definition iso9660.h:34
#define ISO9660_PRIMARY_LBA
ISO9660 Primary Volume Descriptor block address.
Definition iso9660.h:37
#define ISO9660_ID
ISO9660 identifier.
Definition iso9660.h:43
#define list_first_entry(list, type, member)
Get the container of the first entry in a list.
Definition list.h:334
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition list.h:94
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
#define list_empty(list)
Test whether a list is empty.
Definition list.h:137
#define LIST_HEAD(list)
Declare a static list head.
Definition list.h:38
#define list_check_contains_entry(entry, head, member)
Check list contains a specified entry.
Definition list.h:550
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
uint8_t block[3][8]
DES-encrypted blocks.
Definition mschapv2.h:1
uint32_t control
Control.
Definition myson.h:3
int xfer_open_uri(struct interface *intf, struct uri *uri)
Open URI.
Definition open.c:68
Data transfer interface opening.
uint32_t blksize
Cipher block size.
Definition pccrr.h:1
void process_del(struct process *process)
Remove process from process list.
Definition process.c:80
void step(void)
Single-step a single process.
Definition process.c:99
void process_add(struct process *process)
Add process to process list.
Definition process.c:60
Processes.
#define PROC_DESC_ONCE(object_type, process, _step)
Define a process descriptor for a process that runs only once.
Definition process.h:98
static void process_init_stopped(struct process *process, struct process_descriptor *desc, struct refcnt *refcnt)
Initialise process without adding to process list.
Definition process.h:146
void unquiesce(void)
Unquiesce system.
Definition quiesce.c:47
void quiesce(void)
Quiesce system.
Definition quiesce.c:37
Quiesce system.
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition retry.c:65
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition retry.c:118
static struct process_descriptor sanpath_process_desc
SAN path process descriptor.
Definition sanboot.c:340
static void sandev_restart(struct san_device *sandev, int rc)
Restart SAN device interface.
Definition sanboot.c:349
static int sandev_rw(struct san_device *sandev, uint64_t lba, unsigned int count, void *buffer, int(*block_rw)(struct interface *control, struct interface *data, uint64_t lba, unsigned int count, void *buffer, size_t len))
Read from or write to SAN device.
Definition sanboot.c:598
static void sanpath_block_close(struct san_path *sanpath, int rc)
Handle closure of underlying block device interface.
Definition sanboot.c:270
static void sandev_command_close(struct san_device *sandev, int rc)
Close SAN device command.
Definition sanboot.c:144
static int sandev_command(struct san_device *sandev, int(*command)(struct san_device *sandev, const union san_command_params *params), const union san_command_params *params)
Execute a single SAN device command and wait for completion.
Definition sanboot.c:511
static unsigned long san_retries
Number of times to retry commands.
Definition sanboot.c:84
static void sandev_undescribe(struct san_device *sandev)
Remove SAN device descriptors.
Definition sanboot.c:740
int sandev_read(struct san_device *sandev, uint64_t lba, unsigned int count, void *buffer)
Read from SAN device.
Definition sanboot.c:647
static void sandev_command_expired(struct retry_timer *timer, int over __unused)
Handle SAN device command timeout.
Definition sanboot.c:185
static struct interface_descriptor sanpath_block_desc
SAN path block interface descriptor.
Definition sanboot.c:336
#define SAN_DEFAULT_RETRIES
Default number of times to retry commands.
Definition sanboot.c:68
static int sandev_parse_iso9660(struct san_device *sandev)
Configure SAN device as a CD-ROM, if applicable.
Definition sanboot.c:768
int sandev_reopen(struct san_device *sandev)
(Re)open SAN device
Definition sanboot.c:373
static int sanpath_open(struct san_path *sanpath)
Open SAN path.
Definition sanboot.c:199
unsigned int san_default_drive(void)
Get default SAN drive number.
Definition sanboot.c:973
#define SAN_COMMAND_TIMEOUT
Timeout for block device commands (in ticks)
Definition sanboot.c:58
static int sandev_command_rw(struct san_device *sandev, const union san_command_params *params)
Initiate SAN device read/write command.
Definition sanboot.c:452
int register_sandev(struct san_device *sandev, unsigned int drive, unsigned int flags)
Register SAN device.
Definition sanboot.c:880
static struct interface_operation sanpath_block_op[]
SAN path block interface operations.
Definition sanboot.c:329
static void sanpath_step(struct san_path *sanpath)
SAN path process.
Definition sanboot.c:302
static void sandev_free(struct refcnt *refcnt)
Free SAN device.
Definition sanboot.c:123
int sandev_write(struct san_device *sandev, uint64_t lba, unsigned int count, void *buffer)
Write to SAN device.
Definition sanboot.c:668
struct san_device * sandev_next(unsigned int drive)
Find next SAN device by drive number.
Definition sanboot.c:108
static struct interface_operation sandev_command_op[]
SAN device command interface operations.
Definition sanboot.c:170
int sandev_reset(struct san_device *sandev)
Reset SAN device.
Definition sanboot.c:576
void unregister_sandev(struct san_device *sandev)
Unregister SAN device.
Definition sanboot.c:942
struct san_device * alloc_sandev(struct uri **uris, unsigned int count, size_t priv_size)
Allocate SAN device.
Definition sanboot.c:837
static int sandev_command_read_capacity(struct san_device *sandev, const union san_command_params *params __unused)
Initiate SAN device read capacity command.
Definition sanboot.c:482
#define SAN_REOPEN_DELAY_SECS
Delay between reopening attempts.
Definition sanboot.c:78
static void sandev_command_capacity(struct san_device *sandev, struct block_device_capacity *capacity)
Record SAN device capacity.
Definition sanboot.c:162
static struct interface_descriptor sandev_command_desc
SAN device command interface descriptor.
Definition sanboot.c:177
struct san_device * sandev_find(unsigned int drive)
Find SAN device by drive number.
Definition sanboot.c:92
static void sanpath_close(struct san_path *sanpath, int rc)
Close SAN path.
Definition sanboot.c:241
static size_t sanpath_block_window(struct san_path *sanpath __unused)
Check flow control window.
Definition sanboot.c:288
static int sandev_describe(struct san_device *sandev)
Describe SAN device.
Definition sanboot.c:697
static int sandev_apply(void)
Apply SAN boot settings.
Definition sanboot.c:998
int fetch_uint_setting(struct settings *settings, const struct setting *setting, unsigned long *value)
Fetch value of unsigned integer setting.
Definition settings.c:1040
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
An ACPI descriptor (used to construct ACPI tables)
Definition acpi.h:295
struct list_head list
List of ACPI descriptors for this model.
Definition acpi.h:301
Block device capacity.
Definition blockdev.h:18
unsigned int max_count
Maximum number of blocks per single transfer.
Definition blockdev.h:24
size_t blksize
Block size.
Definition blockdev.h:22
A command-line command.
Definition command.h:10
An object interface descriptor.
Definition interface.h:56
An object interface operation.
Definition interface.h:18
An object interface.
Definition interface.h:125
An ISO9660 Primary Volume Descriptor (fixed portion)
Definition iso9660.h:20
An ISO9660 Primary Volume Descriptor.
Definition iso9660.h:28
A process descriptor.
Definition process.h:32
A process.
Definition process.h:18
A reference counter.
Definition refcnt.h:27
A retry timer.
Definition retry.h:22
SAN device read/write command parameters.
Definition sanboot.c:426
uint64_t lba
Starting LBA.
Definition sanboot.c:434
unsigned int count
Block count.
Definition sanboot.c:436
void * buffer
Data buffer.
Definition sanboot.c:432
int(* block_rw)(struct interface *control, struct interface *data, uint64_t lba, unsigned int count, void *buffer, size_t len)
SAN device read/write operation.
Definition sanboot.c:428
A SAN device.
Definition sanboot.h:59
void * priv
Driver private data.
Definition sanboot.h:90
struct san_path * active
Current active path.
Definition sanboot.h:95
struct retry_timer timer
Command timeout timer.
Definition sanboot.h:73
unsigned int drive
Drive number.
Definition sanboot.h:66
struct refcnt refcnt
Reference count.
Definition sanboot.h:61
unsigned int blksize_shift
Block size shift.
Definition sanboot.h:85
struct list_head opened
List of opened SAN paths.
Definition sanboot.h:97
struct interface command
Command interface.
Definition sanboot.h:71
unsigned int paths
Number of paths.
Definition sanboot.h:93
struct block_device_capacity capacity
Raw block device capacity.
Definition sanboot.h:78
unsigned int flags
Flags.
Definition sanboot.h:68
int command_rc
Command status.
Definition sanboot.h:75
int is_cdrom
Drive is a CD-ROM.
Definition sanboot.h:87
struct list_head list
List of SAN devices.
Definition sanboot.h:63
struct list_head closed
List of closed SAN paths.
Definition sanboot.h:99
struct san_path path[0]
SAN paths.
Definition sanboot.h:101
A SAN path.
Definition sanboot.h:37
struct list_head list
List of open/closed paths.
Definition sanboot.h:45
struct process process
Process.
Definition sanboot.h:50
struct acpi_descriptor * desc
ACPI descriptor (if applicable)
Definition sanboot.h:55
int path_rc
Path status.
Definition sanboot.h:52
unsigned int index
Path index.
Definition sanboot.h:41
struct interface block
Underlying block device interface.
Definition sanboot.h:48
struct uri * uri
SAN device URI.
Definition sanboot.h:43
struct san_device * sandev
Containing SAN device.
Definition sanboot.h:39
A setting.
Definition settings.h:24
A settings applicator.
Definition settings.h:252
A timer.
Definition timer.h:29
A Uniform Resource Identifier.
Definition uri.h:65
void sleep_fixed(unsigned int secs)
Sleep (uninterruptibly) for a fixed number of seconds.
Definition timer.c:144
int32_t before
Initial microcode version.
Definition ucode.h:5
SAN device command parameters.
Definition sanboot.c:440
struct san_command_rw_params rw
Read/write command parameters.
Definition sanboot.c:442
static struct uri * uri_get(struct uri *uri)
Increment URI reference count.
Definition uri.h:195
static void uri_put(struct uri *uri)
Decrement URI reference count.
Definition uri.h:206
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition xfer.c:117
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition xfer.c:147
Data transfer interfaces.