Annotation of qemu/roms/ipxe/src/drivers/nvs/nvs.c, revision 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.