Annotation of qemu/roms/ipxe/src/drivers/nvs/nvs.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (C) 2006 Michael Brown <[email protected]>.
                      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 <stdint.h>
                     22: #include <string.h>
                     23: #include <errno.h>
                     24: #include <assert.h>
                     25: #include <ipxe/nvs.h>
                     26: 
                     27: /** @file
                     28:  *
                     29:  * Non-volatile storage
                     30:  *
                     31:  */
                     32: 
                     33: /**
                     34:  * Calculate length up to next block boundary
                     35:  *
                     36:  * @v nvs              NVS device
                     37:  * @v address          Starting address
                     38:  * @v max_len          Maximum length
                     39:  * @ret len            Length to use, stopping at block boundaries
                     40:  */
                     41: static size_t nvs_frag_len ( struct nvs_device *nvs, unsigned int address,
                     42:                             size_t max_len ) {
                     43:        size_t frag_len;
                     44: 
                     45:        /* If there are no block boundaries, return the maximum length */
                     46:        if ( ! nvs->block_size )
                     47:                return max_len;
                     48: 
                     49:        /* Calculate space remaining up to next block boundary */
                     50:        frag_len = ( ( nvs->block_size -
                     51:                       ( address & ( nvs->block_size - 1 ) ) )
                     52:                     << nvs->word_len_log2 );
                     53: 
                     54:        /* Limit to maximum length */
                     55:        if ( max_len < frag_len )
                     56:                return max_len;
                     57: 
                     58:        return frag_len;
                     59: }
                     60: 
                     61: /**
                     62:  * Read from non-volatile storage device
                     63:  *
                     64:  * @v nvs              NVS device
                     65:  * @v address          Address from which to read
                     66:  * @v data             Data buffer
                     67:  * @v len              Length of data buffer
                     68:  * @ret rc             Return status code
                     69:  */
                     70: int nvs_read ( struct nvs_device *nvs, unsigned int address,
                     71:               void *data, size_t len ) {
                     72:        size_t frag_len;
                     73:        int rc;
                     74: 
                     75:        /* We don't even attempt to handle buffer lengths that aren't
                     76:         * an integral number of words.
                     77:         */
                     78:        assert ( ( len & ( ( 1 << nvs->word_len_log2 ) - 1 ) ) == 0 );
                     79: 
                     80:        while ( len ) {
                     81: 
                     82:                /* Calculate length to read, stopping at block boundaries */
                     83:                frag_len = nvs_frag_len ( nvs, address, len );
                     84: 
                     85:                /* Read this portion of the buffer from the device */
                     86:                if ( ( rc = nvs->read ( nvs, address, data, frag_len ) ) != 0 )
                     87:                        return rc;
                     88: 
                     89:                /* Update parameters */
                     90:                data += frag_len;
                     91:                address += ( frag_len >> nvs->word_len_log2 );
                     92:                len -= frag_len;
                     93:        }
                     94: 
                     95:        return 0;
                     96: }
                     97: 
                     98: /**
                     99:  * Verify content of non-volatile storage device
                    100:  *
                    101:  * @v nvs              NVS device
                    102:  * @v address          Address from which to read
                    103:  * @v data             Data to compare against
                    104:  * @v len              Length of data buffer
                    105:  * @ret rc             Return status code
                    106:  */
                    107: static int nvs_verify ( struct nvs_device *nvs, unsigned int address,
                    108:                        const void *data, size_t len ) {
                    109:        uint8_t read_data[len];
                    110:        int rc;
                    111: 
                    112:        /* Read data into temporary buffer */
                    113:        if ( ( rc = nvs_read ( nvs, address, read_data, len ) ) != 0 )
                    114:                return rc;
                    115: 
                    116:        /* Compare data */
                    117:        if ( memcmp ( data, read_data, len ) != 0 ) {
                    118:                DBG ( "NVS %p verification failed at %#04x+%zd\n",
                    119:                      nvs, address, len );
                    120:                return -EIO;
                    121:        }
                    122: 
                    123:        return 0;
                    124: }
                    125: 
                    126: /**
                    127:  * Write to non-volatile storage device
                    128:  *
                    129:  * @v nvs              NVS device
                    130:  * @v address          Address to which to write
                    131:  * @v data             Data buffer
                    132:  * @v len              Length of data buffer
                    133:  * @ret rc             Return status code
                    134:  */
                    135: int nvs_write ( struct nvs_device *nvs, unsigned int address,
                    136:                const void *data, size_t len ) {
                    137:        size_t frag_len;
                    138:        int rc;
                    139: 
                    140:        /* We don't even attempt to handle buffer lengths that aren't
                    141:         * an integral number of words.
                    142:         */
                    143:        assert ( ( len & ( ( 1 << nvs->word_len_log2 ) - 1 ) ) == 0 );
                    144: 
                    145:        while ( len ) {
                    146: 
                    147:                /* Calculate length to write, stopping at block boundaries */
                    148:                frag_len = nvs_frag_len ( nvs, address, len );
                    149: 
                    150:                /* Write this portion of the buffer to the device */
                    151:                if ( ( rc = nvs->write ( nvs, address, data, frag_len ) ) != 0)
                    152:                        return rc;
                    153: 
                    154:                /* Read back and verify data */
                    155:                if ( ( rc = nvs_verify ( nvs, address, data, frag_len ) ) != 0)
                    156:                        return rc;
                    157: 
                    158:                /* Update parameters */
                    159:                data += frag_len;
                    160:                address += ( frag_len >> nvs->word_len_log2 );
                    161:                len -= frag_len;
                    162:        }
                    163: 
                    164:        return 0;
                    165: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.