iPXE
sanboot.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2017 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 /**
00027  * @file
00028  *
00029  * SAN booting
00030  *
00031  */
00032 
00033 #include <stdint.h>
00034 #include <stdlib.h>
00035 #include <errno.h>
00036 #include <assert.h>
00037 #include <ipxe/xfer.h>
00038 #include <ipxe/open.h>
00039 #include <ipxe/timer.h>
00040 #include <ipxe/process.h>
00041 #include <ipxe/iso9660.h>
00042 #include <ipxe/dhcp.h>
00043 #include <ipxe/settings.h>
00044 #include <ipxe/quiesce.h>
00045 #include <ipxe/sanboot.h>
00046 
00047 /**
00048  * Default SAN drive number
00049  *
00050  * The drive number is a meaningful concept only in a BIOS
00051  * environment, where it represents the INT13 drive number (0x80 for
00052  * the first hard disk).  We retain it in other environments to allow
00053  * for a simple way for iPXE commands to refer to SAN drives.
00054  */
00055 #define SAN_DEFAULT_DRIVE 0x80
00056 
00057 /**
00058  * Timeout for block device commands (in ticks)
00059  *
00060  * Underlying devices should ideally never become totally stuck.
00061  * However, if they do, then the blocking SAN APIs provide no means
00062  * for the caller to cancel the operation, and the machine appears to
00063  * hang.  Use an overall timeout for all commands to avoid this
00064  * problem and bounce timeout failures to the caller.
00065  */
00066 #define SAN_COMMAND_TIMEOUT ( 15 * TICKS_PER_SEC )
00067 
00068 /**
00069  * Default number of times to retry commands
00070  *
00071  * We may need to retry commands.  For example, the underlying
00072  * connection may be closed by the SAN target due to an inactivity
00073  * timeout, or the SAN target may return pointless "error" messages
00074  * such as "SCSI power-on occurred".
00075  */
00076 #define SAN_DEFAULT_RETRIES 10
00077 
00078 /**
00079  * Delay between reopening attempts
00080  *
00081  * Some SAN targets will always accept connections instantly and
00082  * report a temporary unavailability by e.g. failing the TEST UNIT
00083  * READY command.  Avoid bombarding such targets by introducing a
00084  * small delay between attempts.
00085  */
00086 #define SAN_REOPEN_DELAY_SECS 5
00087 
00088 /** List of SAN devices */
00089 LIST_HEAD ( san_devices );
00090 
00091 /** Number of times to retry commands */
00092 static unsigned long san_retries = SAN_DEFAULT_RETRIES;
00093 
00094 /**
00095  * Find SAN device by drive number
00096  *
00097  * @v drive             Drive number
00098  * @ret sandev          SAN device, or NULL
00099  */
00100 struct san_device * sandev_find ( unsigned int drive ) {
00101         struct san_device *sandev;
00102 
00103         list_for_each_entry ( sandev, &san_devices, list ) {
00104                 if ( sandev->drive == drive )
00105                         return sandev;
00106         }
00107         return NULL;
00108 }
00109 
00110 /**
00111  * Free SAN device
00112  *
00113  * @v refcnt            Reference count
00114  */
00115 static void sandev_free ( struct refcnt *refcnt ) {
00116         struct san_device *sandev =
00117                 container_of ( refcnt, struct san_device, refcnt );
00118         unsigned int i;
00119 
00120         assert ( ! timer_running ( &sandev->timer ) );
00121         assert ( ! sandev->active );
00122         assert ( list_empty ( &sandev->opened ) );
00123         for ( i = 0 ; i < sandev->paths ; i++ ) {
00124                 uri_put ( sandev->path[i].uri );
00125                 assert ( sandev->path[i].desc == NULL );
00126         }
00127         free ( sandev );
00128 }
00129 
00130 /**
00131  * Close SAN device command
00132  *
00133  * @v sandev            SAN device
00134  * @v rc                Reason for close
00135  */
00136 static void sandev_command_close ( struct san_device *sandev, int rc ) {
00137 
00138         /* Stop timer */
00139         stop_timer ( &sandev->timer );
00140 
00141         /* Restart interface */
00142         intf_restart ( &sandev->command, rc );
00143 
00144         /* Record command status */
00145         sandev->command_rc = rc;
00146 }
00147 
00148 /**
00149  * Record SAN device capacity
00150  *
00151  * @v sandev            SAN device
00152  * @v capacity          SAN device capacity
00153  */
00154 static void sandev_command_capacity ( struct san_device *sandev,
00155                                       struct block_device_capacity *capacity ) {
00156 
00157         /* Record raw capacity information */
00158         memcpy ( &sandev->capacity, capacity, sizeof ( sandev->capacity ) );
00159 }
00160 
00161 /** SAN device command interface operations */
00162 static struct interface_operation sandev_command_op[] = {
00163         INTF_OP ( intf_close, struct san_device *, sandev_command_close ),
00164         INTF_OP ( block_capacity, struct san_device *,
00165                   sandev_command_capacity ),
00166 };
00167 
00168 /** SAN device command interface descriptor */
00169 static struct interface_descriptor sandev_command_desc =
00170         INTF_DESC ( struct san_device, command, sandev_command_op );
00171 
00172 /**
00173  * Handle SAN device command timeout
00174  *
00175  * @v retry             Retry timer
00176  */
00177 static void sandev_command_expired ( struct retry_timer *timer,
00178                                      int over __unused ) {
00179         struct san_device *sandev =
00180                 container_of ( timer, struct san_device, timer );
00181 
00182         sandev_command_close ( sandev, -ETIMEDOUT );
00183 }
00184 
00185 /**
00186  * Open SAN path
00187  *
00188  * @v sanpath           SAN path
00189  * @ret rc              Return status code
00190  */
00191 static int sanpath_open ( struct san_path *sanpath ) {
00192         struct san_device *sandev = sanpath->sandev;
00193         int rc;
00194 
00195         /* Sanity check */
00196         list_check_contains_entry ( sanpath, &sandev->closed, list );
00197 
00198         /* Open interface */
00199         if ( ( rc = xfer_open_uri ( &sanpath->block, sanpath->uri ) ) != 0 ) {
00200                 DBGC ( sandev, "SAN %#02x.%d could not (re)open URI: "
00201                        "%s\n", sandev->drive, sanpath->index, strerror ( rc ) );
00202                 return rc;
00203         }
00204 
00205         /* Update ACPI descriptor, if applicable */
00206         if ( ! ( sandev->flags & SAN_NO_DESCRIBE ) ) {
00207                 if ( sanpath->desc )
00208                         acpi_del ( sanpath->desc );
00209                 sanpath->desc = acpi_describe ( &sanpath->block );
00210                 if ( sanpath->desc )
00211                         acpi_add ( sanpath->desc );
00212         }
00213 
00214         /* Start process */
00215         process_add ( &sanpath->process );
00216 
00217         /* Mark as opened */
00218         list_del ( &sanpath->list );
00219         list_add_tail ( &sanpath->list, &sandev->opened );
00220 
00221         /* Record as in progress */
00222         sanpath->path_rc = -EINPROGRESS;
00223 
00224         return 0;
00225 }
00226 
00227 /**
00228  * Close SAN path
00229  *
00230  * @v sanpath           SAN path
00231  * @v rc                Reason for close
00232  */
00233 static void sanpath_close ( struct san_path *sanpath, int rc ) {
00234         struct san_device *sandev = sanpath->sandev;
00235 
00236         /* Record status */
00237         sanpath->path_rc = rc;
00238 
00239         /* Mark as closed */
00240         list_del ( &sanpath->list );
00241         list_add_tail ( &sanpath->list, &sandev->closed );
00242 
00243         /* Stop process */
00244         process_del ( &sanpath->process );
00245 
00246         /* Restart interfaces, avoiding potential loops */
00247         if ( sanpath == sandev->active ) {
00248                 intfs_restart ( rc, &sandev->command, &sanpath->block, NULL );
00249                 sandev->active = NULL;
00250                 sandev_command_close ( sandev, rc );
00251         } else {
00252                 intf_restart ( &sanpath->block, rc );
00253         }
00254 }
00255 
00256 /**
00257  * Handle closure of underlying block device interface
00258  *
00259  * @v sanpath           SAN path
00260  * @v rc                Reason for close
00261  */
00262 static void sanpath_block_close ( struct san_path *sanpath, int rc ) {
00263         struct san_device *sandev = sanpath->sandev;
00264 
00265         /* Any closure is an error from our point of view */
00266         if ( rc == 0 )
00267                 rc = -ENOTCONN;
00268         DBGC ( sandev, "SAN %#02x.%d closed: %s\n",
00269                sandev->drive, sanpath->index, strerror ( rc ) );
00270 
00271         /* Close path */
00272         sanpath_close ( sanpath, rc );
00273 }
00274 
00275 /**
00276  * Check flow control window
00277  *
00278  * @v sanpath           SAN path
00279  */
00280 static size_t sanpath_block_window ( struct san_path *sanpath __unused ) {
00281 
00282         /* We are never ready to receive data via this interface.
00283          * This prevents objects that support both block and stream
00284          * interfaces from attempting to send us stream data.
00285          */
00286         return 0;
00287 }
00288 
00289 /**
00290  * SAN path process
00291  *
00292  * @v sanpath           SAN path
00293  */
00294 static void sanpath_step ( struct san_path *sanpath ) {
00295         struct san_device *sandev = sanpath->sandev;
00296 
00297         /* Ignore if we are already the active device */
00298         if ( sanpath == sandev->active )
00299                 return;
00300 
00301         /* Wait until path has become available */
00302         if ( ! xfer_window ( &sanpath->block ) )
00303                 return;
00304 
00305         /* Record status */
00306         sanpath->path_rc = 0;
00307 
00308         /* Mark as active path or close as applicable */
00309         if ( ! sandev->active ) {
00310                 DBGC ( sandev, "SAN %#02x.%d is active\n",
00311                        sandev->drive, sanpath->index );
00312                 sandev->active = sanpath;
00313         } else {
00314                 DBGC ( sandev, "SAN %#02x.%d is available\n",
00315                        sandev->drive, sanpath->index );
00316                 sanpath_close ( sanpath, 0 );
00317         }
00318 }
00319 
00320 /** SAN path block interface operations */
00321 static struct interface_operation sanpath_block_op[] = {
00322         INTF_OP ( intf_close, struct san_path *, sanpath_block_close ),
00323         INTF_OP ( xfer_window, struct san_path *, sanpath_block_window ),
00324         INTF_OP ( xfer_window_changed, struct san_path *, sanpath_step ),
00325 };
00326 
00327 /** SAN path block interface descriptor */
00328 static struct interface_descriptor sanpath_block_desc =
00329         INTF_DESC ( struct san_path, block, sanpath_block_op );
00330 
00331 /** SAN path process descriptor */
00332 static struct process_descriptor sanpath_process_desc =
00333         PROC_DESC_ONCE ( struct san_path, process, sanpath_step );
00334 
00335 /**
00336  * Restart SAN device interface
00337  *
00338  * @v sandev            SAN device
00339  * @v rc                Reason for restart
00340  */
00341 static void sandev_restart ( struct san_device *sandev, int rc ) {
00342         struct san_path *sanpath;
00343 
00344         /* Restart all block device interfaces */
00345         while ( ( sanpath = list_first_entry ( &sandev->opened,
00346                                                struct san_path, list ) ) ) {
00347                 sanpath_close ( sanpath, rc );
00348         }
00349 
00350         /* Clear active path */
00351         sandev->active = NULL;
00352 
00353         /* Close any outstanding command */
00354         sandev_command_close ( sandev, rc );
00355 }
00356 
00357 /**
00358  * (Re)open SAN device
00359  *
00360  * @v sandev            SAN device
00361  * @ret rc              Return status code
00362  *
00363  * This function will block until the device is available.
00364  */
00365 int sandev_reopen ( struct san_device *sandev ) {
00366         struct san_path *sanpath;
00367         int rc;
00368 
00369         /* Unquiesce system */
00370         unquiesce();
00371 
00372         /* Close any outstanding command and restart interfaces */
00373         sandev_restart ( sandev, -ECONNRESET );
00374         assert ( sandev->active == NULL );
00375         assert ( list_empty ( &sandev->opened ) );
00376 
00377         /* Open all paths */
00378         while ( ( sanpath = list_first_entry ( &sandev->closed,
00379                                                struct san_path, list ) ) ) {
00380                 if ( ( rc = sanpath_open ( sanpath ) ) != 0 )
00381                         goto err_open;
00382         }
00383 
00384         /* Wait for any device to become available, or for all devices
00385          * to fail.
00386          */
00387         while ( sandev->active == NULL ) {
00388                 step();
00389                 if ( list_empty ( &sandev->opened ) ) {
00390                         /* Get status of the first device to be
00391                          * closed.  Do this on the basis that earlier
00392                          * errors (e.g. "invalid IQN") are probably
00393                          * more interesting than later errors
00394                          * (e.g. "TCP timeout").
00395                          */
00396                         rc = -ENODEV;
00397                         list_for_each_entry ( sanpath, &sandev->closed, list ) {
00398                                 rc = sanpath->path_rc;
00399                                 break;
00400                         }
00401                         DBGC ( sandev, "SAN %#02x never became available: %s\n",
00402                                sandev->drive, strerror ( rc ) );
00403                         goto err_none;
00404                 }
00405         }
00406 
00407         assert ( ! list_empty ( &sandev->opened ) );
00408         return 0;
00409 
00410  err_none:
00411  err_open:
00412         sandev_restart ( sandev, rc );
00413         return rc;
00414 }
00415 
00416 /** SAN device read/write command parameters */
00417 struct san_command_rw_params {
00418         /** SAN device read/write operation */
00419         int ( * block_rw ) ( struct interface *control, struct interface *data,
00420                              uint64_t lba, unsigned int count,
00421                              userptr_t buffer, size_t len );
00422         /** Data buffer */
00423         userptr_t buffer;
00424         /** Starting LBA */
00425         uint64_t lba;
00426         /** Block count */
00427         unsigned int count;
00428 };
00429 
00430 /** SAN device command parameters */
00431 union san_command_params {
00432         /** Read/write command parameters */
00433         struct san_command_rw_params rw;
00434 };
00435 
00436 /**
00437  * Initiate SAN device read/write command
00438  *
00439  * @v sandev            SAN device
00440  * @v params            Command parameters
00441  * @ret rc              Return status code
00442  */
00443 static int sandev_command_rw ( struct san_device *sandev,
00444                                const union san_command_params *params ) {
00445         struct san_path *sanpath = sandev->active;
00446         size_t len = ( params->rw.count * sandev->capacity.blksize );
00447         int rc;
00448 
00449         /* Sanity check */
00450         assert ( sanpath != NULL );
00451 
00452         /* Initiate read/write command */
00453         if ( ( rc = params->rw.block_rw ( &sanpath->block, &sandev->command,
00454                                           params->rw.lba, params->rw.count,
00455                                           params->rw.buffer, len ) ) != 0 ) {
00456                 DBGC ( sandev, "SAN %#02x.%d could not initiate read/write: "
00457                        "%s\n", sandev->drive, sanpath->index, strerror ( rc ) );
00458                 return rc;
00459         }
00460 
00461         return 0;
00462 }
00463 
00464 /**
00465  * Initiate SAN device read capacity command
00466  *
00467  * @v sandev            SAN device
00468  * @v params            Command parameters
00469  * @ret rc              Return status code
00470  */
00471 static int
00472 sandev_command_read_capacity ( struct san_device *sandev,
00473                                const union san_command_params *params __unused){
00474         struct san_path *sanpath = sandev->active;
00475         int rc;
00476 
00477         /* Sanity check */
00478         assert ( sanpath != NULL );
00479 
00480         /* Initiate read capacity command */
00481         if ( ( rc = block_read_capacity ( &sanpath->block,
00482                                           &sandev->command ) ) != 0 ) {
00483                 DBGC ( sandev, "SAN %#02x.%d could not initiate read capacity: "
00484                        "%s\n", sandev->drive, sanpath->index, strerror ( rc ) );
00485                 return rc;
00486         }
00487 
00488         return 0;
00489 }
00490 
00491 /**
00492  * Execute a single SAN device command and wait for completion
00493  *
00494  * @v sandev            SAN device
00495  * @v command           Command
00496  * @v params            Command parameters (if required)
00497  * @ret rc              Return status code
00498  */
00499 static int
00500 sandev_command ( struct san_device *sandev,
00501                  int ( * command ) ( struct san_device *sandev,
00502                                      const union san_command_params *params ),
00503                  const union san_command_params *params ) {
00504         unsigned int retries = 0;
00505         int rc;
00506 
00507         /* Sanity check */
00508         assert ( ! timer_running ( &sandev->timer ) );
00509 
00510         /* Unquiesce system */
00511         unquiesce();
00512 
00513         /* (Re)try command */
00514         do {
00515 
00516                 /* Reopen block device if applicable */
00517                 if ( sandev_needs_reopen ( sandev ) &&
00518                      ( ( rc = sandev_reopen ( sandev ) ) != 0 ) ) {
00519 
00520                         /* Delay reopening attempts */
00521                         sleep_fixed ( SAN_REOPEN_DELAY_SECS );
00522 
00523                         /* Retry opening indefinitely for multipath devices */
00524                         if ( sandev->paths <= 1 )
00525                                 retries++;
00526 
00527                         continue;
00528                 }
00529 
00530                 /* Initiate command */
00531                 if ( ( rc = command ( sandev, params ) ) != 0 ) {
00532                         retries++;
00533                         continue;
00534                 }
00535 
00536                 /* Start expiry timer */
00537                 start_timer_fixed ( &sandev->timer, SAN_COMMAND_TIMEOUT );
00538 
00539                 /* Wait for command to complete */
00540                 while ( timer_running ( &sandev->timer ) )
00541                         step();
00542 
00543                 /* Check command status */
00544                 if ( ( rc = sandev->command_rc ) != 0 ) {
00545                         retries++;
00546                         continue;
00547                 }
00548 
00549                 return 0;
00550 
00551         } while ( retries <= san_retries );
00552 
00553         /* Sanity check */
00554         assert ( ! timer_running ( &sandev->timer ) );
00555 
00556         return rc;
00557 }
00558 
00559 /**
00560  * Reset SAN device
00561  *
00562  * @v sandev            SAN device
00563  * @ret rc              Return status code
00564  */
00565 int sandev_reset ( struct san_device *sandev ) {
00566         int rc;
00567 
00568         DBGC ( sandev, "SAN %#02x reset\n", sandev->drive );
00569 
00570         /* Close and reopen underlying block device */
00571         if ( ( rc = sandev_reopen ( sandev ) ) != 0 )
00572                 return rc;
00573 
00574         return 0;
00575 }
00576 
00577 /**
00578  * Read from or write to SAN device
00579  *
00580  * @v sandev            SAN device
00581  * @v lba               Starting logical block address
00582  * @v count             Number of logical blocks
00583  * @v buffer            Data buffer
00584  * @v block_rw          Block read/write method
00585  * @ret rc              Return status code
00586  */
00587 static int sandev_rw ( struct san_device *sandev, uint64_t lba,
00588                        unsigned int count, userptr_t buffer,
00589                        int ( * block_rw ) ( struct interface *control,
00590                                             struct interface *data,
00591                                             uint64_t lba, unsigned int count,
00592                                             userptr_t buffer, size_t len ) ) {
00593         union san_command_params params;
00594         unsigned int remaining;
00595         size_t frag_len;
00596         int rc;
00597 
00598         /* Initialise command parameters */
00599         params.rw.block_rw = block_rw;
00600         params.rw.buffer = buffer;
00601         params.rw.lba = ( lba << sandev->blksize_shift );
00602         params.rw.count = sandev->capacity.max_count;
00603         remaining = ( count << sandev->blksize_shift );
00604 
00605         /* Read/write fragments */
00606         while ( remaining ) {
00607 
00608                 /* Determine fragment length */
00609                 if ( params.rw.count > remaining )
00610                         params.rw.count = remaining;
00611 
00612                 /* Execute command */
00613                 if ( ( rc = sandev_command ( sandev, sandev_command_rw,
00614                                              &params ) ) != 0 )
00615                         return rc;
00616 
00617                 /* Move to next fragment */
00618                 frag_len = ( sandev->capacity.blksize * params.rw.count );
00619                 params.rw.buffer = userptr_add ( params.rw.buffer, frag_len );
00620                 params.rw.lba += params.rw.count;
00621                 remaining -= params.rw.count;
00622         }
00623 
00624         return 0;
00625 }
00626 
00627 /**
00628  * Read from SAN device
00629  *
00630  * @v sandev            SAN device
00631  * @v lba               Starting logical block address
00632  * @v count             Number of logical blocks
00633  * @v buffer            Data buffer
00634  * @ret rc              Return status code
00635  */
00636 int sandev_read ( struct san_device *sandev, uint64_t lba,
00637                   unsigned int count, userptr_t buffer ) {
00638         int rc;
00639 
00640         /* Read from device */
00641         if ( ( rc = sandev_rw ( sandev, lba, count, buffer, block_read ) ) != 0 )
00642                 return rc;
00643 
00644         return 0;
00645 }
00646 
00647 /**
00648  * Write to SAN device
00649  *
00650  * @v sandev            SAN device
00651  * @v lba               Starting logical block address
00652  * @v count             Number of logical blocks
00653  * @v buffer            Data buffer
00654  * @ret rc              Return status code
00655  */
00656 int sandev_write ( struct san_device *sandev, uint64_t lba,
00657                    unsigned int count, userptr_t buffer ) {
00658         int rc;
00659 
00660         /* Write to device */
00661         if ( ( rc = sandev_rw ( sandev, lba, count, buffer, block_write ) ) != 0 )
00662                 return rc;
00663 
00664         /* Quiesce system.  This is a heuristic designed to ensure
00665          * that the system is quiesced before Windows starts up, since
00666          * a Windows SAN boot will typically write a status flag to
00667          * the disk as its last action before transferring control to
00668          * the native drivers.
00669          */
00670         quiesce();
00671 
00672         return 0;
00673 }
00674 
00675 /**
00676  * Describe SAN device
00677  *
00678  * @v sandev            SAN device
00679  * @ret rc              Return status code
00680  *
00681  * Allow connections to progress until all existent path descriptors
00682  * are complete.
00683  */
00684 static int sandev_describe ( struct san_device *sandev ) {
00685         struct san_path *sanpath;
00686         struct acpi_descriptor *desc;
00687         int rc;
00688 
00689         /* Wait for all paths to be either described or closed */
00690         while ( 1 ) {
00691 
00692                 /* Allow connections to progress */
00693                 step();
00694 
00695                 /* Fail if any closed path has an incomplete descriptor */
00696                 list_for_each_entry ( sanpath, &sandev->closed, list ) {
00697                         desc = sanpath->desc;
00698                         if ( ! desc )
00699                                 continue;
00700                         if ( ( rc = desc->model->complete ( desc ) ) != 0 ) {
00701                                 DBGC ( sandev, "SAN %#02x.%d could not be "
00702                                        "described: %s\n", sandev->drive,
00703                                        sanpath->index, strerror ( rc ) );
00704                                 return rc;
00705                         }
00706                 }
00707 
00708                 /* Succeed if no paths have an incomplete descriptor */
00709                 rc = 0;
00710                 list_for_each_entry ( sanpath, &sandev->opened, list ) {
00711                         desc = sanpath->desc;
00712                         if ( ! desc )
00713                                 continue;
00714                         if ( ( rc = desc->model->complete ( desc ) ) != 0 )
00715                                 break;
00716                 }
00717                 if ( rc == 0 )
00718                         return 0;
00719         }
00720 }
00721 
00722 /**
00723  * Remove SAN device descriptors
00724  *
00725  * @v sandev            SAN device
00726  */
00727 static void sandev_undescribe ( struct san_device *sandev ) {
00728         struct san_path *sanpath;
00729         unsigned int i;
00730 
00731         /* Remove all ACPI descriptors */
00732         for ( i = 0 ; i < sandev->paths ; i++ ) {
00733                 sanpath = &sandev->path[i];
00734                 if ( sanpath->desc ) {
00735                         acpi_del ( sanpath->desc );
00736                         sanpath->desc = NULL;
00737                 }
00738         }
00739 }
00740 
00741 /**
00742  * Configure SAN device as a CD-ROM, if applicable
00743  *
00744  * @v sandev            SAN device
00745  * @ret rc              Return status code
00746  *
00747  * Both BIOS and UEFI require SAN devices to be accessed with a block
00748  * size of 2048.  While we could require the user to configure the
00749  * block size appropriately, this is non-trivial and would impose a
00750  * substantial learning effort on the user.  Instead, we check for the
00751  * presence of the ISO9660 primary volume descriptor and, if found,
00752  * then we force a block size of 2048 and map read/write requests
00753  * appropriately.
00754  */
00755 static int sandev_parse_iso9660 ( struct san_device *sandev ) {
00756         static const struct iso9660_primary_descriptor_fixed primary_check = {
00757                 .type = ISO9660_TYPE_PRIMARY,
00758                 .id = ISO9660_ID,
00759         };
00760         union {
00761                 struct iso9660_primary_descriptor primary;
00762                 char bytes[ISO9660_BLKSIZE];
00763         } *scratch;
00764         unsigned int blksize;
00765         unsigned int blksize_shift;
00766         unsigned int lba;
00767         unsigned int count;
00768         int rc;
00769 
00770         /* Calculate required blocksize shift for potential CD-ROM access */
00771         blksize = sandev->capacity.blksize;
00772         blksize_shift = 0;
00773         while ( blksize < ISO9660_BLKSIZE ) {
00774                 blksize <<= 1;
00775                 blksize_shift++;
00776         }
00777         if ( blksize > ISO9660_BLKSIZE ) {
00778                 /* Cannot be a CD-ROM.  This is not an error. */
00779                 rc = 0;
00780                 goto invalid_blksize;
00781         }
00782         lba = ( ISO9660_PRIMARY_LBA << blksize_shift );
00783         count = ( 1 << blksize_shift );
00784 
00785         /* Allocate scratch area */
00786         scratch = malloc ( ISO9660_BLKSIZE );
00787         if ( ! scratch ) {
00788                 rc = -ENOMEM;
00789                 goto err_alloc;
00790         }
00791 
00792         /* Read primary volume descriptor */
00793         if ( ( rc = sandev_read ( sandev, lba, count,
00794                                   virt_to_user ( scratch ) ) ) != 0 ) {
00795                 DBGC ( sandev, "SAN %#02x could not read ISO9660 primary"
00796                        "volume descriptor: %s\n",
00797                        sandev->drive, strerror ( rc ) );
00798                 goto err_rw;
00799         }
00800 
00801         /* Configure as CD-ROM if applicable */
00802         if ( memcmp ( &scratch->primary.fixed, &primary_check,
00803                       sizeof ( primary_check ) ) == 0 ) {
00804                 DBGC ( sandev, "SAN %#02x contains an ISO9660 filesystem; "
00805                        "treating as CD-ROM\n", sandev->drive );
00806                 sandev->blksize_shift = blksize_shift;
00807                 sandev->is_cdrom = 1;
00808         }
00809 
00810  err_rw:
00811         free ( scratch );
00812  err_alloc:
00813  invalid_blksize:
00814         return rc;
00815 }
00816 
00817 /**
00818  * Allocate SAN device
00819  *
00820  * @v uris              List of URIs
00821  * @v count             Number of URIs
00822  * @v priv_size         Size of private data
00823  * @ret sandev          SAN device, or NULL
00824  */
00825 struct san_device * alloc_sandev ( struct uri **uris, unsigned int count,
00826                                    size_t priv_size ) {
00827         struct san_device *sandev;
00828         struct san_path *sanpath;
00829         size_t size;
00830         unsigned int i;
00831 
00832         /* Allocate and initialise structure */
00833         size = ( sizeof ( *sandev ) + ( count * sizeof ( sandev->path[0] ) ) );
00834         sandev = zalloc ( size + priv_size );
00835         if ( ! sandev )
00836                 return NULL;
00837         ref_init ( &sandev->refcnt, sandev_free );
00838         intf_init ( &sandev->command, &sandev_command_desc, &sandev->refcnt );
00839         timer_init ( &sandev->timer, sandev_command_expired, &sandev->refcnt );
00840         sandev->priv = ( ( ( void * ) sandev ) + size );
00841         sandev->paths = count;
00842         INIT_LIST_HEAD ( &sandev->opened );
00843         INIT_LIST_HEAD ( &sandev->closed );
00844         for ( i = 0 ; i < count ; i++ ) {
00845                 sanpath = &sandev->path[i];
00846                 sanpath->sandev = sandev;
00847                 sanpath->index = i;
00848                 sanpath->uri = uri_get ( uris[i] );
00849                 list_add_tail ( &sanpath->list, &sandev->closed );
00850                 intf_init ( &sanpath->block, &sanpath_block_desc,
00851                             &sandev->refcnt );
00852                 process_init_stopped ( &sanpath->process, &sanpath_process_desc,
00853                                        &sandev->refcnt );
00854                 sanpath->path_rc = -EINPROGRESS;
00855         }
00856 
00857         return sandev;
00858 }
00859 
00860 /**
00861  * Register SAN device
00862  *
00863  * @v sandev            SAN device
00864  * @v drive             Drive number
00865  * @v flags             Flags
00866  * @ret rc              Return status code
00867  */
00868 int register_sandev ( struct san_device *sandev, unsigned int drive,
00869                       unsigned int flags ) {
00870         int rc;
00871 
00872         /* Check that drive number is not in use */
00873         if ( sandev_find ( drive ) != NULL ) {
00874                 DBGC ( sandev, "SAN %#02x is already in use\n", drive );
00875                 rc = -EADDRINUSE;
00876                 goto err_in_use;
00877         }
00878 
00879         /* Record drive number and flags */
00880         sandev->drive = drive;
00881         sandev->flags = flags;
00882 
00883         /* Check that device is capable of being opened (i.e. that all
00884          * URIs are well-formed and that at least one path is
00885          * working).
00886          */
00887         if ( ( rc = sandev_reopen ( sandev ) ) != 0 )
00888                 goto err_reopen;
00889 
00890         /* Describe device */
00891         if ( ( rc = sandev_describe ( sandev ) ) != 0 )
00892                 goto err_describe;
00893 
00894         /* Read device capacity */
00895         if ( ( rc = sandev_command ( sandev, sandev_command_read_capacity,
00896                                      NULL ) ) != 0 )
00897                 goto err_capacity;
00898 
00899         /* Configure as a CD-ROM, if applicable */
00900         if ( ( rc = sandev_parse_iso9660 ( sandev ) ) != 0 )
00901                 goto err_iso9660;
00902 
00903         /* Add to list of SAN devices */
00904         list_add_tail ( &sandev->list, &san_devices );
00905         DBGC ( sandev, "SAN %#02x registered\n", sandev->drive );
00906 
00907         return 0;
00908 
00909         list_del ( &sandev->list );
00910  err_iso9660:
00911  err_capacity:
00912  err_describe:
00913  err_reopen:
00914         sandev_restart ( sandev, rc );
00915         sandev_undescribe ( sandev );
00916  err_in_use:
00917         return rc;
00918 }
00919 
00920 /**
00921  * Unregister SAN device
00922  *
00923  * @v sandev            SAN device
00924  */
00925 void unregister_sandev ( struct san_device *sandev ) {
00926 
00927         /* Sanity check */
00928         assert ( ! timer_running ( &sandev->timer ) );
00929 
00930         /* Remove from list of SAN devices */
00931         list_del ( &sandev->list );
00932 
00933         /* Shut down interfaces */
00934         sandev_restart ( sandev, 0 );
00935 
00936         /* Remove ACPI descriptors */
00937         sandev_undescribe ( sandev );
00938 
00939         DBGC ( sandev, "SAN %#02x unregistered\n", sandev->drive );
00940 }
00941 
00942 /** The "san-drive" setting */
00943 const struct setting san_drive_setting __setting ( SETTING_SANBOOT_EXTRA,
00944                                                    san-drive ) = {
00945         .name = "san-drive",
00946         .description = "SAN drive number",
00947         .tag = DHCP_EB_SAN_DRIVE,
00948         .type = &setting_type_uint8,
00949 };
00950 
00951 /**
00952  * Get default SAN drive number
00953  *
00954  * @ret drive           Default drive number
00955  */
00956 unsigned int san_default_drive ( void ) {
00957         unsigned long drive;
00958 
00959         /* Use "san-drive" setting, if specified */
00960         if ( fetch_uint_setting ( NULL, &san_drive_setting, &drive ) >= 0 )
00961                 return drive;
00962 
00963         /* Otherwise, default to booting from first hard disk */
00964         return SAN_DEFAULT_DRIVE;
00965 }
00966 
00967 /** The "san-retries" setting */
00968 const struct setting san_retries_setting __setting ( SETTING_SANBOOT_EXTRA,
00969                                                      san-retries ) = {
00970         .name = "san-retries",
00971         .description = "SAN retry count",
00972         .tag = DHCP_EB_SAN_RETRY,
00973         .type = &setting_type_int8,
00974 };
00975 
00976 /**
00977  * Apply SAN boot settings
00978  *
00979  * @ret rc              Return status code
00980  */
00981 static int sandev_apply ( void ) {
00982 
00983         /* Apply "san-retries" setting */
00984         if ( fetch_uint_setting ( NULL, &san_retries_setting,
00985                                   &san_retries ) < 0 ) {
00986                 san_retries = SAN_DEFAULT_RETRIES;
00987         }
00988 
00989         return 0;
00990 }
00991 
00992 /** Settings applicator */
00993 struct settings_applicator sandev_applicator __settings_applicator = {
00994         .apply = sandev_apply,
00995 };