Home | History | Annotate | Download | only in block
      1 /*
      2  * Copyright (C) 2007 Michael Brown <mbrown (at) 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., 675 Mass Ave, Cambridge, MA 02139, USA.
     17  */
     18 
     19 FILE_LICENCE ( GPL2_OR_LATER );
     20 
     21 #include <gpxe/blockdev.h>
     22 #include <gpxe/ramdisk.h>
     23 
     24 /**
     25  * @file
     26  *
     27  * RAM disks
     28  *
     29  */
     30 
     31 static inline __attribute__ (( always_inline )) struct ramdisk *
     32 block_to_ramdisk ( struct block_device *blockdev ) {
     33 	return container_of ( blockdev, struct ramdisk, blockdev );
     34 }
     35 
     36 /**
     37  * Read block
     38  *
     39  * @v blockdev		Block device
     40  * @v block		Block number
     41  * @v count		Block count
     42  * @v buffer		Data buffer
     43  * @ret rc		Return status code
     44  */
     45 static int ramdisk_read ( struct block_device *blockdev, uint64_t block,
     46 			  unsigned long count, userptr_t buffer ) {
     47 	struct ramdisk *ramdisk = block_to_ramdisk ( blockdev );
     48 	unsigned long offset = ( block * blockdev->blksize );
     49 	unsigned long length = ( count * blockdev->blksize );
     50 
     51 	DBGC ( ramdisk, "RAMDISK %p reading [%lx,%lx)\n",
     52 	       ramdisk, offset, length );
     53 
     54 	memcpy_user ( buffer, 0, ramdisk->data, offset, length );
     55 	return 0;
     56 }
     57 
     58 /**
     59  * Write block
     60  *
     61  * @v blockdev		Block device
     62  * @v block		Block number
     63  * @v count		Block count
     64  * @v buffer		Data buffer
     65  * @ret rc		Return status code
     66  */
     67 static int ramdisk_write ( struct block_device *blockdev, uint64_t block,
     68 			   unsigned long count, userptr_t buffer ) {
     69 	struct ramdisk *ramdisk = block_to_ramdisk ( blockdev );
     70 	unsigned long offset = ( block * blockdev->blksize );
     71 	unsigned long length = ( count * blockdev->blksize );
     72 
     73 	DBGC ( ramdisk, "RAMDISK %p writing [%lx,%lx)\n",
     74 	       ramdisk, offset, length );
     75 
     76 	memcpy_user ( ramdisk->data, offset, buffer, 0, length );
     77 	return 0;
     78 }
     79 
     80 static struct block_device_operations ramdisk_operations = {
     81 	.read	= ramdisk_read,
     82 	.write	= ramdisk_write
     83 };
     84 
     85 int init_ramdisk ( struct ramdisk *ramdisk, userptr_t data, size_t len,
     86 		   unsigned int blksize ) {
     87 
     88 	if ( ! blksize )
     89 		blksize = 512;
     90 
     91 	ramdisk->data = data;
     92 	ramdisk->blockdev.op = &ramdisk_operations;
     93 	ramdisk->blockdev.blksize = blksize;
     94 	ramdisk->blockdev.blocks = ( len / blksize );
     95 
     96 	return 0;
     97 }
     98