/* This file is part of libforensic1394. Copyright (C) 2010 Freddie Witherden libforensic1394 is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. libforensic1394 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with libforensic1394. If not, see . */ /** * \file forensic1394.h * * \brief Main header file for libforensic1394. */ /** * \mainpage libforensic1394 * * The latest version of libforensic1394 can be found at: * https://freddie.witherden.org/tools/libforensic1394/ * * This API gives you access to the FireWire bus of contemporary operating * systems in order to facilitate digital forensics on an attached device. * Unlike existing APIs Forensic1394 is: * - Modern; unlike existing FireWire libraries Forensic1394 supports the * new `Juju' stack introduced in Linux 2.6.22. * - Portable; with platform drivers existing for both Linux (Juju stack * only) and Mac OS X (via I/O Kit). * - Minimal; only functions required for performing digital forensics are * provided. * * By omitting features not required in forensic applications (such as * isochronous transfers) the API is both simple to use and port. For example * the memory of an attached device can be read using the following code: * * \code * forensic1394_bus *bus; * forensic1394_dev **dev; * char data[512]; * * // Allocate a bus handle * bus = forensic1394_alloc(); * assert(bus); * * // Enabls SBP-2; required for memory access to some systems * forensic1394_enable_sbp2(bus); * * // Give the bus time to reinitialise * sleep(2); * * // Get the devices attached to the systen * dev = forensic1394_get_devices(bus, NULL, NULL); * assert(dev); * * // Open the first device * forensic1394_open_device(dev[0]); * * // Read some memory from the device * forensic1394_read_device(dev[0], 50 * 1024 * 1024, 512, data); * * // Data now contains 512 bytes of memory starting at an offset of 50MiB * * // Close the device and destroy the bus * forensic1394_close_device(dev[0]); * forensic1394_destroy(bus); * \endcode * * \section sbp2 Enabling SBP-2 * In order to gain direct memory access to certain systems, namely Windows and * GNU/Linux, it is necessary to present the target system with an SBP-2 unit * directory. This can be done by calling ::forensic1394_enable_sbp2. It is * usual for devices on the bus to take a couple of seconds to react to this * change. Therefore, client applications should ideally wait for ~2 seconds * before attempting to read or write to a device. Although there are * provisions in the SBP-2 specification to determine when a target system has * enabled the DMA filter, client-side API limitations currently prevent * libforensic1394 from leveraging this. * * \section reset Handling Bus Resets * Bus resets occur when devices are added/removed from the system or when the * configuration ROM of a device is updated. The following methods are * affected by bus resets: * - ::forensic1394_open_device * - ::forensic1394_read_device * - ::forensic1394_read_device_v * - ::forensic1394_write_device * - ::forensic1394_write_device_v * * After a bus reset calls to all of these methods will result in * #FORENSIC1394_RESULT_BUS_RESET being returned. Applications should * handle this by saving the GUIDs of any devices being accessed and then call * ::forensic1394_get_devices. Calling this will void all device handles. * The new list of devices can then be iterated through and their GUIDs * compared against saved GUIDs. The GUID of a device can be obtained by * calling ::forensic1394_get_device_guid. * * \section thread Thread Safety * libforensic1394 is thread safe at the device level with the restriction * that devices can only be accessed by the thread that opened them. This is * because some backends, namely Mac OS X/IOKit, install thread-specific * callback dispatchers upon opening a device. When using multiple threads of * execution care must be taken when calling ::forensic1394_get_devices (which * closes and destroys any open device handles). It is the responsibility of * the caller to ensure that this is safe. The process can be simplified * through the use of an \a ondestroy callback handler. * * \author Freddie Witherden */ #ifndef _FORENSIC_1394_H #define _FORENSIC_1394_H #ifdef __cplusplus extern "C" { #endif #if defined(FORENSIC1394_DECL) // No op #elif defined(_MSC_VER) # define FORENSIC1394_DECL __declspec(dllexport) #elif (__GNUC__ >= 3) # define FORENSIC1394_DECL __attribute__((visibility("default"))) #else # define FORENSIC1394_DECL #endif #include #include /// An opaque bus handle typedef struct _forensic1394_bus forensic1394_bus; /// An opaque device handle typedef struct _forensic1394_dev forensic1394_dev; /** * \brief A request structure used for making batch read/write requests. * * For use with the batch APIs (suffixed by _v) requests allow * forensic1394 to take advantage of the asynchronous capabilities of * FireWire stacks in order to improve performance. * * \sa forensic1394_read_device_v * \sa forensic1394_write_device_v */ typedef struct _forensic1394_req { /// The address to read/write uint64_t addr; /// Length of the buffer in bytes size_t len; /// Data buffer void *buf; } forensic1394_req; /** * \brief Number of uint32 elements required to store a device ROM. * * A FireWire configuration status ROM (CSR) is made up of unsigned 32-bit * integers. The maximum size of a ROM is 1024 bytes, giving 256 elements. */ #define FORENSIC1394_CSR_SZ 256 /** * A function to be called when a ::forensic1394_dev is about to be destroyed. * This should be passed to ::forensic1394_get_devices and will be associated * with all devices returned by the method. The callback will fire either when * the bus is destroyed via ::forensic1394_destroy or the next time that * ::forensic1394_get_devices is called (which has the implicit effect of * destroying all existing devices first). * * If user data is required it can be attached on either a per-bus or per-device * level. * * \param bus The bus owning the device. * \param dev The device being destroyed. * * \sa forensic1394_set_bus_user_data * \sa forensic1394_set_device_user_data */ typedef void (*forensic1394_device_callback) (forensic1394_bus *bus, forensic1394_dev *dev); /** * \brief Possible return status codes. * * In general methods return 0 on success and a negative integer on failure. * These codes may be used to ascertain precisely why a method failed. It is * worth noting that invalid input parameters are handled with assertions as * opposed to status codes. * * \sa forensic1394_get_result_str */ typedef enum { /// No errors encountered FORENSIC1394_RESULT_SUCCESS = 0, /// General, unspecified, error FORENSIC1394_RESULT_OTHER_ERROR = -1, /// A bus reset has occured FORENSIC1394_RESULT_BUS_RESET = -2, /// Permissions related error FORENSIC1394_RESULT_NO_PERM = -3, /// Device is busy FORENSIC1394_RESULT_BUSY = -4, /// General I/O error FORENSIC1394_RESULT_IO_ERROR = -5, /// Bad transfer size (normally too large) FORENSIC1394_RESULT_IO_SIZE = -6, /// I/O Timeout FORENSIC1394_RESULT_IO_TIMEOUT = -7, /// Sentinel; internal use only FORENSIC1394_RESULT_END = -8 } forensic1394_result; /** * \brief Allocates a new forensic1394 handle. * * This handle can then be used to query the devices attached to the bus and to * update the configuration status ROM (CSR) of the bus. * * \return A handle to a forensic1394_bus on success, NULL otherwise. */ FORENSIC1394_DECL forensic1394_bus *forensic1394_alloc(void); /** * \brief Provides an SBP-2 unit directory; required for DMA to Windows systems. * * Updates the configuration status ROM of the bus to contain an SBP-2 * unit directory. This is required in order for some connected * devices to allow for direct memory access (`DMA'). * * Note that this is usually a global change, affecting all FireWire * ports on the system. * * As calling this method usually results in a bus reset it is advisable to * call it as soon as a bus is available. * * \param bus The 1394 bus to add the SBP-2 unit directory to. * \return A result status code. */ FORENSIC1394_DECL forensic1394_result forensic1394_enable_sbp2(forensic1394_bus *bus); /** * \brief Gets the devices attached to the FireWire bus. * * This method scans the (foreign) devices attached to \a bus and returns a * NULL-terminated list of them. * * The out-parameter \a ndev, if not NULL, serves a dual purpose. After a call * to the function if \a *ndev is: * * - >= 0 then the call was successful and it contains the number of devices * attached to the system, which may be 0 if no devices are attached. * - < 0 then the call was not successful and it contains the appropriate * ::forensic1394_result error code. * * Getting the attached devices is a destructive process; voiding any existing * device handles. To compensate for this the \a ondestroy callback is * provided. This argument, if not NULL, will be called when the new device * list is destroyed, usually as a result of a subsequent call to * ::forensic1394_get_devices or a call to ::forensic1394_destroy. The * function is called for each device in the list. * * \warning Calling this method will invalidate all active device handles. * * \param bus The bus to get the devices for. * \param[out] ndev The number of devices found; NULL is acceptable. * \param[in] ondestroy Function to be called when the returned device list is * destroyed; NULL for no callback. * \return A NULL-terminated list of devices. * * \sa forensic1394_device_callback * \sa forensic1394_result */ FORENSIC1394_DECL forensic1394_dev ** forensic1394_get_devices(forensic1394_bus *bus, int *ndev, forensic1394_device_callback ondestroy); /** * \brief Destroys a bus handle. * * Releases all of the memory associated with the handle, closing any open * devices. After a call to this method all forensic1394 device handles are * invalidated. * * \param bus The forensic1394_bus to destroy. */ FORENSIC1394_DECL void forensic1394_destroy(forensic1394_bus *bus); /** * \brief Fetches the user data for \a bus. * * Returns the user data for \a bus. If ::forensic1394_set_bus_user_data is * yet to be called on the bus the result is undefined. * * \param bus The bus. * \return The user data associated with the bus. * * \sa forensic1394_set_bus_user_data */ FORENSIC1394_DECL void * forensic1394_get_bus_user_data(forensic1394_bus *bus); /** * \brief Sets the user data for the bus. * * \param bus The bus. * \param[in] u The user data to set. * * \sa forensic1394_get_bus_user_data */ FORENSIC1394_DECL void forensic1394_set_bus_user_data(forensic1394_bus *bus, void *u); /** * \brief Opens the device \a dev for reading/writing. * * It is necessary to open a device before attempting to read/write from it. * * \param dev The device to open. * \return A result status code. * * \sa forensic1394_close_device */ FORENSIC1394_DECL forensic1394_result forensic1394_open_device(forensic1394_dev *dev); /** * \brief Closes the device \a dev. * * This can only be called on an open device. * * \param dev The device to close. */ FORENSIC1394_DECL void forensic1394_close_device(forensic1394_dev *dev); /** * \brief Checks if a device is open or not. * * \param dev The FireWire device. * \return Non-zero if the device is open; 0 if it is closed. */ FORENSIC1394_DECL int forensic1394_is_device_open(forensic1394_dev *dev); /** * \brief Reads \a len bytes from \a dev starting at \a addr into \a buf. * * Performs a blocking (synchronous) read on the device \a dev, starting at the * address \a addr and attempting to read \a len bytes. The resulting bytes * are copied into \a buf. * * It is worth noting that many devices impose a limit on the maximum transfer * size. This limit can be obtained by calling * ::forensic1394_get_device_request_size and is usually 2048 bytes in size. * * This method is a convenience wrapper around ::forensic1394_read_device_v. * * \param dev The device to read from. * \param addr The memory address to start reading from. * \param len The number of bytes to read. * \param[out] buf The buffer to copy the read bytes into; must be at least * \a len bytes in size. * \return A result status code. * * \sa forensic1394_get_device_request_size * \sa forensic1394_read_device_v */ FORENSIC1394_DECL forensic1394_result forensic1394_read_device(forensic1394_dev *dev, uint64_t addr, size_t len, void *buf); /** * \brief Reads each request specified in \a req from \a dev asynchronously. * * Vectorised, scatter input, read method. By issuing requests asynchronously * this function is often able to offer better performance than a series of * ::forensic1394_read_device calls. The performance gains, if any, depend * heavily on the capabilities of the backend. * * Each request must be no larger than ::forensic1394_get_device_request_size * bytes. If any of the data buffers in \a req overlap then the behaviour * is undefined. * * The method will return early should one of the requests fail. It is not * currently possible to determine which request caused the error. * * \param dev The device to read from. * \param req The read requests to service. * \param nreq The number of requests in \a req. * \return A result status code. */ FORENSIC1394_DECL forensic1394_result forensic1394_read_device_v(forensic1394_dev *dev, forensic1394_req *req, size_t nreq); /** * \brief Writes \a len bytes from \a buf to \a dev starting at \a addr. * * Performs a blocking (synchronous) write on the device \a dev attempting to * copy \a len bytes from \a buf to the device address \a addr. See * the documentation for ::forensic1394_read_device for a discussion on the * maximum transfer size. * * This method is a convenience wrapper around ::forensic1394_write_device_v. * * \param dev The device to write to. * \param addr The memory address to start writing to. * \param len The number of bytes to write. * \param[in] buf The buffer to write. * \return A result status code. * * \a forensic1394_read_device */ FORENSIC1394_DECL forensic1394_result forensic1394_write_device(forensic1394_dev *dev, uint64_t addr, size_t len, void *buf); /** * \brief Writes each request specified in \a req to \a dev asynchronously. * * The vectorised, gather output, write method. Depending on the backend this * method may issue the requests in \a req asynchronously in order to improve * performance. See ::forensic1394_read_device_v for further discussion. * * \param dev The device to write to. * \param[in] req The write requests to service. * \param nreq The number of requests in \a req. * \return A result status code. */ FORENSIC1394_DECL forensic1394_result forensic1394_write_device_v(forensic1394_dev *dev, const forensic1394_req *req, size_t nreq); /** * \brief Copies the configuration ROM for the device \a dev into \a rom. * * Fetches the configuration status ROM (CSR) for the device and copies it * into \a rom. This is assumed to be of at least #FORENSIC1394_CSR_SZ * elements in size. Any unused space will be filled with zeros. * * \param dev The device. * \param rom The array to copy the CSR into. */ FORENSIC1394_DECL void forensic1394_get_device_csr(forensic1394_dev *dev, uint32_t *rom); /** * \brief Returns the node ID of the device. * * It is important to note that this value does not remain constant across bus * resets and is hence unsuitable for device identification. * * \param dev The device. * \return The node ID of the device. */ FORENSIC1394_DECL uint16_t forensic1394_get_device_node_id(forensic1394_dev *dev); /** * \brief Returns the GUID of the device. * * This is a 48-bit value, similar to a MAC address, that uniquely identifies * a FireWire device. * * \param dev The device. * \return The GUID of the device. */ FORENSIC1394_DECL int64_t forensic1394_get_device_guid(forensic1394_dev *dev); /** * \brief Returns the product name of the device, if any. * * Should the property not exist for the device an empty string ("") is * returned. The string is guaranteed to remain valid for the lifetime of the * device. * * \param dev The device. * \return The product name of the device, if any. */ FORENSIC1394_DECL const char * forensic1394_get_device_product_name(forensic1394_dev *dev); /** * \brief Returns the product ID of the device, if any. * * Should the property not exist then 0 is returned. * * \param dev The device. * \return The product ID of the device, or 0 if it is not defined. */ FORENSIC1394_DECL int forensic1394_get_device_product_id(forensic1394_dev *dev); /** * \brief Returns the vendor name of the device, if any. * * Should the property not exist for the device an empty string ("") is * returned. The string is guaranteed to remain valid for the lifetime of the * device. * * \param dev The device. * \return The vendor name of the device, if any. */ FORENSIC1394_DECL const char * forensic1394_get_device_vendor_name(forensic1394_dev *dev); /** * \brief Returns the vendor ID of the device, if any. * * Should the property not exist then 0 is returned. * * \param dev The device. * \return The vendor ID of the device, or 0 if it is not defined. */ FORENSIC1394_DECL int forensic1394_get_device_vendor_id(forensic1394_dev *dev); /** * \brief Returns the maximum request size supported by the device. * * Parses the configuration status ROM for the device and extracts the maximum * supported request size (usually 2048 bytes). This value should be taken as * an upper-bound for the length of read/write calls. If a size can not be * found in the CSR then 512 bytes will be returned. * * The returned size is guaranteed to be a positive power of two. * * \param dev The device. * \return The maximum request size in bytes. */ FORENSIC1394_DECL int forensic1394_get_device_request_size(forensic1394_dev *dev); /** * \brief Fetches the user data for the device \a dev. * * If ::forensic1394_set_device_user_data is yet to be called on the device the * result is undefined. * * \param dev The device. * \return The user data associated with the device. * * \sa forensic1394_set_device_user_data */ FORENSIC1394_DECL void * forensic1394_get_device_user_data(forensic1394_dev *dev); /** * \brief Sets the user data for the device \a dev to \a u. * * \param dev The device. * \param[in] u The user data to set. * * \sa forensic1394_get_device_user_data */ FORENSIC1394_DECL void forensic1394_set_device_user_data(forensic1394_dev *dev, void *u); /** * \brief Converts a return status code to a string. * * Returns a textual representation of the return status code \a result. The * string returned is guaranteed to be valid for the lifetime of the program. * * In the event of an invalid code NULL is returned. * * \param r The return status code. * \return A description of the error code on success; NULL otherwise. */ FORENSIC1394_DECL const char * forensic1394_get_result_str(forensic1394_result r); #ifdef __cplusplus } #endif #endif // _FORENSIC_1394_H .