source: bootcd/isolinux/syslinux-6.03/gpxe/src/drivers/nvs/nvs.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

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