| /* | |
| * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. | |
| * | |
| * This program is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU General Public License as | |
| * published by the Free Software Foundation; either version 2 of the | |
| * License, or any later version. | |
| * | |
| * This program 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 | |
| * General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU General Public License | |
| * along with this program; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| * 02110-1301, USA. | |
| * | |
| * You can also choose to distribute this program under the terms of | |
| * the Unmodified Binary Distribution Licence (as given in the file | |
| * COPYING.UBDL), provided that you have satisfied its requirements. | |
| */ | |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); | |
| FILE_SECBOOT ( PERMITTED ); | |
| #include <errno.h> | |
| #include <ipxe/bitmap.h> | |
| /** @file | |
| * | |
| * Bitmaps for multicast downloads | |
| * | |
| */ | |
| /** | |
| * Resize bitmap | |
| * | |
| * @v bitmap Bitmap | |
| * @v new_length New length of bitmap, in bits | |
| * @ret rc Return status code | |
| */ | |
| int bitmap_resize ( struct bitmap *bitmap, unsigned int new_length ) { | |
| unsigned int old_num_blocks; | |
| unsigned int new_num_blocks; | |
| size_t new_size; | |
| bitmap_block_t *new_blocks; | |
| old_num_blocks = BITMAP_BLOCKS ( bitmap->length ); | |
| new_num_blocks = BITMAP_BLOCKS ( new_length ); | |
| if ( old_num_blocks != new_num_blocks ) { | |
| new_size = ( new_num_blocks * sizeof ( bitmap->blocks[0] ) ); | |
| new_blocks = realloc ( bitmap->blocks, new_size ); | |
| if ( ! new_blocks ) { | |
| DBGC ( bitmap, "Bitmap %p could not resize to %d " | |
| "bits\n", bitmap, new_length ); | |
| return -ENOMEM; | |
| } | |
| bitmap->blocks = new_blocks; | |
| } | |
| bitmap->length = new_length; | |
| while ( old_num_blocks < new_num_blocks ) { | |
| bitmap->blocks[old_num_blocks++] = 0; | |
| } | |
| DBGC ( bitmap, "Bitmap %p resized to %d bits\n", bitmap, new_length ); | |
| return 0; | |
| } | |
| /** | |
| * Test bit in bitmap | |
| * | |
| * @v bitmap Bitmap | |
| * @v bit Bit index | |
| * @ret is_set Bit is set | |
| */ | |
| int bitmap_test ( struct bitmap *bitmap, unsigned int bit ) { | |
| unsigned int index = BITMAP_INDEX ( bit ); | |
| bitmap_block_t mask = BITMAP_MASK ( bit ); | |
| /* Treat out-of-range bits as implicitly being zero */ | |
| if ( bit >= bitmap->length ) | |
| return 0; | |
| return ( ( bitmap->blocks[index] & mask ) != 0 ); | |
| } | |
| /** | |
| * Set bit in bitmap | |
| * | |
| * @v bitmap Bitmap | |
| * @v bit Bit index | |
| * @ret rc Return status code | |
| */ | |
| int bitmap_set ( struct bitmap *bitmap, unsigned int bit ) { | |
| unsigned int index = BITMAP_INDEX ( bit ); | |
| bitmap_block_t mask = BITMAP_MASK ( bit ); | |
| DBGC ( bitmap, "Bitmap %p setting bit %d\n", bitmap, bit ); | |
| /* Fail if we cannot set this bit */ | |
| if ( bit >= bitmap->length ) { | |
| DBGC ( bitmap, "Bitmap %p bit %d is outside range [0,%d)\n", | |
| bitmap, bit, bitmap->length ); | |
| return -ERANGE; | |
| } | |
| /* Update bitmap */ | |
| bitmap->blocks[index] |= mask; | |
| /* Update first gap counter */ | |
| while ( bitmap_test ( bitmap, bitmap->first_gap ) ) { | |
| bitmap->first_gap++; | |
| } | |
| return 0; | |
| } |