diff options
author | Waldemar Brodkorb <wbx@openadk.org> | 2017-12-31 18:47:16 +0100 |
---|---|---|
committer | Waldemar Brodkorb <wbx@openadk.org> | 2017-12-31 18:47:25 +0100 |
commit | 3a96085b999220c4da0c5ef7d1f7ba26b9ddfb98 (patch) | |
tree | 77f1445aae2e6be5135594e95986b3278bbc061c /package/aboot/src/tools/bio.c | |
parent | cc28479164b8dc8afd4310716da32f16022f5974 (diff) |
dec-multia: make netboot possible, add aboot bootloader
Diffstat (limited to 'package/aboot/src/tools/bio.c')
-rw-r--r-- | package/aboot/src/tools/bio.c | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/package/aboot/src/tools/bio.c b/package/aboot/src/tools/bio.c new file mode 100644 index 000000000..c82161e62 --- /dev/null +++ b/package/aboot/src/tools/bio.c @@ -0,0 +1,178 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +/* Buffered I/O functions. By cacheing the most recently used blocks, + * we can cut WAAY down on disk traffic... + */ + +static int bio_fd = -1; +static int bio_counter = 0; +static int bio_blocksize = 0; + +struct bio_buf { + int blkno; + int last_access; + int dirty; + char * data; +}; + +#define NBUFS 32 +struct bio_buf buflist[NBUFS]; + +/* initialize the buffer cache. Blow away anything that may + * have been previously cached... + */ +void +binit(int fd, int blocksize) +{ + int i; + + bio_fd = fd; + bio_blocksize = blocksize; + + for(i = 0; i < NBUFS; i++) { + buflist[i].blkno = 0; + if(buflist[i].data) { + free(buflist[i].data); + } + buflist[i].data = 0; + buflist[i].last_access = 0; + buflist[i].dirty = 0; + } +} + +/* Flush out any dirty blocks */ +void +bflush(void) +{ + int i; + + for(i = 0; i < NBUFS; i++) { + if(buflist[i].dirty) { +#ifdef BIO_DEBUG + printf("bflush: writing block %d\n", buflist[i].blkno); +#endif + lseek(bio_fd, buflist[i].blkno * bio_blocksize, 0); + write(bio_fd, buflist[i].data, bio_blocksize); + buflist[i].dirty = 0; + } + } +} + +/* Read a block. */ +void +bread(int blkno, void * blkbuf) +{ + int i; + int lowcount; + int lowcount_buf; + + /* First, see if the block is already in memory... */ + for(i = 0; i < NBUFS; i++) { + if(buflist[i].blkno == blkno) { + /* Got it! Bump the access count and return. */ + buflist[i].last_access = ++bio_counter; +#ifdef BIO_DEBUG + printf("bread: buffer hit on block %d\n", blkno); +#endif + memcpy(blkbuf, buflist[i].data, bio_blocksize); + return; + } + } + + /* Not in memory; need to find a buffer and read it in. */ + lowcount = buflist[0].last_access; + lowcount_buf = 0; + for(i = 1; i < NBUFS; i++) { + if(buflist[i].last_access < lowcount) { + lowcount = buflist[i].last_access; + lowcount_buf = i; + } + } + + /* If the buffer is dirty, we need to write it out... */ + if(buflist[lowcount_buf].dirty) { +#ifdef BIO_DEBUG + printf("bread: recycling dirty buffer %d for block %d\n", + lowcount_buf, buflist[lowcount_buf].blkno); +#endif + lseek(bio_fd, buflist[lowcount_buf].blkno * bio_blocksize, 0); + write(bio_fd, buflist[lowcount_buf].data, bio_blocksize); + buflist[lowcount_buf].dirty = 0; + } + +#ifdef BIO_DEBUG + printf("bread: Using buffer %d for block %d\n", lowcount_buf, blkno); +#endif + + buflist[lowcount_buf].blkno = blkno; + if(!buflist[lowcount_buf].data) { + buflist[lowcount_buf].data = (char *)malloc(bio_blocksize); + } + lseek(bio_fd, blkno * bio_blocksize, 0); + if(read(bio_fd,buflist[lowcount_buf].data,bio_blocksize)!=bio_blocksize) { + perror("bread: I/O error"); + } + + buflist[lowcount_buf].last_access = ++bio_counter; + memcpy(blkbuf, buflist[lowcount_buf].data, bio_blocksize); +} + + +/* Write a block */ +void +bwrite(int blkno, void * blkbuf) +{ + int i; + int lowcount; + int lowcount_buf; + + /* First, see if the block is already in memory... */ + for(i = 0; i < NBUFS; i++) { + if(buflist[i].blkno == blkno) { + /* Got it! Bump the access count and return. */ +#ifdef BIO_DEBUG + printf("bwrite: buffer hit on block %d\n", blkno); +#endif + buflist[i].last_access = ++bio_counter; + memcpy(buflist[i].data, blkbuf, bio_blocksize); + buflist[i].dirty = 1; + return; + } + } + + /* Not in memory; need to find a buffer and stuff it. */ + lowcount = buflist[0].last_access; + lowcount_buf = 0; + for(i = 1; i < NBUFS; i++) { + if(buflist[i].last_access < lowcount) { + lowcount = buflist[i].last_access; + lowcount_buf = i; + } + } + + /* If the buffer is dirty, we need to write it out... */ + if(buflist[lowcount_buf].dirty) { +#ifdef BIO_DEBUG + printf("bwrite: recycling dirty buffer %d for block %d\n", + lowcount_buf, buflist[lowcount_buf].blkno); +#endif + lseek(bio_fd, buflist[lowcount_buf].blkno * bio_blocksize, 0); + write(bio_fd, buflist[lowcount_buf].data, bio_blocksize); + buflist[lowcount_buf].dirty = 0; + } + +#ifdef BIO_DEBUG + printf("bwrite: Using buffer %d for block %d\n", lowcount_buf, blkno); +#endif + + buflist[lowcount_buf].blkno = blkno; + if(!buflist[lowcount_buf].data) { + buflist[lowcount_buf].data = (char *)malloc(bio_blocksize); + } + buflist[lowcount_buf].last_access = ++bio_counter; + memcpy(buflist[lowcount_buf].data, blkbuf, bio_blocksize); + buflist[lowcount_buf].dirty = 1; +} |