1 #include <blkfront.h>
2 #include <unistd.h>
3 #include <errno.h>
4 #include <string.h>
5 #include <inttypes.h>
6 #include <stdlib.h>
7 #include <stdbool.h>
8 #include <mini-os/byteorder.h>
9 
10 #include "vtpm_manager.h"
11 #include "log.h"
12 #include "uuid.h"
13 
14 #include "vtpmmgr.h"
15 #include "vtpm_disk.h"
16 #include "disk_tpm.h"
17 #include "disk_io.h"
18 
19 static uint8_t disk_staging_buf[4096] __attribute__((aligned(4096)));
20 
21 static struct blkfront_dev* blkdev;
22 static int blkfront_fd = -1;
23 
vtpm_storage_init(void)24 int vtpm_storage_init(void) {
25 	struct blkfront_info info;
26 	blkdev = init_blkfront(NULL, &info);
27 	if (blkdev == NULL)
28 		return -1;
29 	blkfront_fd = blkfront_open(blkdev);
30 	if (blkfront_fd < 0)
31 		return -1;
32 	return 0;
33 }
34 
disk_read_sector(sector_t sector)35 void* disk_read_sector(sector_t sector)
36 {
37 	uint32_t pos = be32_native(sector);
38 	int rc;
39 	vtpmloginfo(VTPM_LOG_VTPM, "disk_read_sector %x\n", pos);
40 	lseek(blkfront_fd, pos * 4096, SEEK_SET);
41 	rc = read(blkfront_fd, disk_staging_buf, 4096);
42 	if (rc != 4096)
43 		abort();
44 	return disk_staging_buf;
45 }
46 
disk_write_buf(void)47 void* disk_write_buf(void) { return disk_staging_buf; }
48 
disk_write_sector(sector_t sector,void * buf,size_t siz)49 void disk_write_sector(sector_t sector, void* buf, size_t siz)
50 {
51 	int rc;
52 	uint32_t pos = be32_native(sector);
53 	lseek(blkfront_fd, pos * 4096, SEEK_SET);
54 	if (siz < 4096) {
55 		if (buf != disk_staging_buf)
56 			memcpy(disk_staging_buf, buf, siz);
57 		memset(disk_staging_buf + siz, 0, 4096 - siz);
58 		buf = disk_staging_buf;
59 	} else if (siz > 4096)
60 		abort();
61 
62 	rc = write(blkfront_fd, buf, 4096);
63 	if (rc != 4096)
64 		abort();
65 }
66 
disk_write_barrier(void)67 void disk_write_barrier(void)
68 {
69 	blkfront_sync(blkdev);
70 }
71 
72 enum inuse_value {
73 	UNUSED,
74 	SLOT_1,
75 	SLOT_2,
76 	SHARED
77 };
78 
79 /* TODO make this dynamic to support using more than 2MB of disk */
80 #define DISK_MAX_SECTOR 0x200
81 
82 /* The first 4 sectors are statically allocated:
83  *  0 - disk header (copy 1)
84  *  1 - disk header (copy 2)
85  *  2 - root sector (copy 1)
86  *  3 - root sector (copy 2)
87  */
88 #define FIRST_DYNAMIC_SECTOR 4
89 
90 static uint8_t sector_inuse_map[DISK_MAX_SECTOR];
91 
active_slot(const struct mem_tpm_mgr * mgr)92 static int active_slot(const struct mem_tpm_mgr *mgr)
93 {
94 	return 1 + mgr->active_root;
95 }
96 
disk_set_used(sector_t loc,const struct mem_tpm_mgr * mgr)97 void disk_set_used(sector_t loc, const struct mem_tpm_mgr *mgr)
98 {
99 	uint32_t s = be32_native(loc);
100 	if (s > DISK_MAX_SECTOR) {
101 		printk("Attempted disk_set_used %x\n", s);
102 		return;
103 	}
104 	sector_inuse_map[s] |= active_slot(mgr);
105 }
106 
disk_flush_slot(const struct mem_tpm_mgr * mgr)107 void disk_flush_slot(const struct mem_tpm_mgr *mgr)
108 {
109 	int i;
110 	for(i = FIRST_DYNAMIC_SECTOR; i < DISK_MAX_SECTOR; i++)
111 		sector_inuse_map[i] &= ~active_slot(mgr);
112 }
113 
disk_find_free(const struct mem_tpm_mgr * mgr)114 sector_t disk_find_free(const struct mem_tpm_mgr *mgr)
115 {
116 	int i;
117 	for(i = FIRST_DYNAMIC_SECTOR; i < DISK_MAX_SECTOR; i++) {
118 		if (sector_inuse_map[i])
119 			continue;
120 		sector_inuse_map[i] = active_slot(mgr);
121 		return native_be32(i);
122 	}
123 	// TODO more graceful error handling (in callers)
124 	abort();
125 }
126