1*dc8fdf3dSkettenis /* $OpenBSD: mdstore.c,v 1.3 2012/11/04 23:30:38 kettenis Exp $ */ 2cceaa36bSkettenis 3cceaa36bSkettenis /* 4cceaa36bSkettenis * Copyright (c) 2012 Mark Kettenis 5cceaa36bSkettenis * 6cceaa36bSkettenis * Permission to use, copy, modify, and distribute this software for any 7cceaa36bSkettenis * purpose with or without fee is hereby granted, provided that the above 8cceaa36bSkettenis * copyright notice and this permission notice appear in all copies. 9cceaa36bSkettenis * 10cceaa36bSkettenis * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11cceaa36bSkettenis * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12cceaa36bSkettenis * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13cceaa36bSkettenis * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14cceaa36bSkettenis * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15cceaa36bSkettenis * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16cceaa36bSkettenis * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17cceaa36bSkettenis */ 18cceaa36bSkettenis 196aace0ceSkettenis #include <assert.h> 20*dc8fdf3dSkettenis #include <err.h> 21cceaa36bSkettenis #include <stdio.h> 226aace0ceSkettenis #include <stdlib.h> 23cceaa36bSkettenis #include <string.h> 24cceaa36bSkettenis 25cceaa36bSkettenis #include "ds.h" 26cceaa36bSkettenis #include "mdstore.h" 27cceaa36bSkettenis #include "util.h" 28cceaa36bSkettenis 29cceaa36bSkettenis void mdstore_start(struct ldc_conn *, uint64_t); 30cceaa36bSkettenis void mdstore_rx_data(struct ldc_conn *, uint64_t, void *, size_t); 31cceaa36bSkettenis 32cceaa36bSkettenis struct ds_service mdstore_service = { 33cceaa36bSkettenis "mdstore", 1, 0, mdstore_start, mdstore_rx_data 34cceaa36bSkettenis }; 35cceaa36bSkettenis 36*dc8fdf3dSkettenis #define MDSET_BEGIN_REQUEST 0x0001 37*dc8fdf3dSkettenis #define MDSET_END_REQUEST 0x0002 38*dc8fdf3dSkettenis #define MD_TRANSFER_REQUEST 0x0003 39cceaa36bSkettenis #define MDSET_LIST_REQUEST 0x0004 406aace0ceSkettenis #define MDSET_SELECT_REQUEST 0x0005 416aace0ceSkettenis #define MDSET_DELETE_REQUEST 0x0006 426aace0ceSkettenis #define MDSET_RETREIVE_REQUEST 0x0007 43cceaa36bSkettenis 44cceaa36bSkettenis struct mdstore_msg { 45cceaa36bSkettenis uint32_t msg_type; 46cceaa36bSkettenis uint32_t payload_len; 47cceaa36bSkettenis uint64_t svc_handle; 48cceaa36bSkettenis uint64_t reqnum; 49cceaa36bSkettenis uint16_t command; 50cceaa36bSkettenis } __packed; 51cceaa36bSkettenis 52*dc8fdf3dSkettenis struct mdstore_begin_end_req { 53*dc8fdf3dSkettenis uint32_t msg_type; 54*dc8fdf3dSkettenis uint32_t payload_len; 55*dc8fdf3dSkettenis uint64_t svc_handle; 56*dc8fdf3dSkettenis uint64_t reqnum; 57*dc8fdf3dSkettenis uint16_t command; 58*dc8fdf3dSkettenis uint16_t nmds; 59*dc8fdf3dSkettenis uint32_t namelen; 60*dc8fdf3dSkettenis char name[1]; 61*dc8fdf3dSkettenis } __packed; 62*dc8fdf3dSkettenis 63*dc8fdf3dSkettenis struct mdstore_transfer_req { 64*dc8fdf3dSkettenis uint32_t msg_type; 65*dc8fdf3dSkettenis uint32_t payload_len; 66*dc8fdf3dSkettenis uint64_t svc_handle; 67*dc8fdf3dSkettenis uint64_t reqnum; 68*dc8fdf3dSkettenis uint16_t command; 69*dc8fdf3dSkettenis uint16_t type; 70*dc8fdf3dSkettenis uint32_t size; 71*dc8fdf3dSkettenis uint64_t offset; 72*dc8fdf3dSkettenis char md[]; 73*dc8fdf3dSkettenis } __packed; 74*dc8fdf3dSkettenis 75*dc8fdf3dSkettenis #define MDSTORE_PRI_TYPE 0x01 76*dc8fdf3dSkettenis #define MDSTORE_HV_MD_TYPE 0x02 77*dc8fdf3dSkettenis #define MDSTORE_CTL_DOM_MD_TYPE 0x04 78*dc8fdf3dSkettenis #define MDSTORE_SVC_DOM_MD_TYPE 0x08 79*dc8fdf3dSkettenis 806aace0ceSkettenis struct mdstore_sel_del_req { 816aace0ceSkettenis uint32_t msg_type; 826aace0ceSkettenis uint32_t payload_len; 836aace0ceSkettenis uint64_t svc_handle; 846aace0ceSkettenis uint64_t reqnum; 856aace0ceSkettenis uint16_t command; 866aace0ceSkettenis uint16_t reserved; 876aace0ceSkettenis uint32_t namelen; 886aace0ceSkettenis char name[1]; 896aace0ceSkettenis } __packed; 906aace0ceSkettenis 91cceaa36bSkettenis #define MDSET_LIST_REPLY 0x0104 92cceaa36bSkettenis 93cceaa36bSkettenis struct mdstore_list_resp { 94cceaa36bSkettenis uint32_t msg_type; 95cceaa36bSkettenis uint32_t payload_len; 96cceaa36bSkettenis uint64_t svc_handle; 97cceaa36bSkettenis uint64_t reqnum; 98cceaa36bSkettenis uint32_t result; 99cceaa36bSkettenis uint16_t booted_set; 100cceaa36bSkettenis uint16_t boot_set; 101cceaa36bSkettenis char sets[1]; 102cceaa36bSkettenis } __packed; 103cceaa36bSkettenis 104cceaa36bSkettenis #define MDST_SUCCESS 0x0 105cceaa36bSkettenis #define MDST_FAILURE 0x1 106cceaa36bSkettenis #define MDST_INVALID_MSG 0x2 107cceaa36bSkettenis #define MDST_MAX_MDS_ERR 0x3 108cceaa36bSkettenis #define MDST_BAD_NAME_ERR 0x4 109cceaa36bSkettenis #define MDST_SET_EXISTS_ERR 0x5 110cceaa36bSkettenis #define MDST_ALLOC_SET_ERR 0x6 111cceaa36bSkettenis #define MDST_ALLOC_MD_ERR 0x7 112cceaa36bSkettenis #define MDST_MD_COUNT_ERR 0x8 113cceaa36bSkettenis #define MDST_MD_SIZE_ERR 0x9 114cceaa36bSkettenis #define MDST_MD_TYPE_ERR 0xa 115cceaa36bSkettenis #define MDST_NOT_EXIST_ERR 0xb 116cceaa36bSkettenis 117cceaa36bSkettenis struct mdstore_set_head mdstore_sets = TAILQ_HEAD_INITIALIZER(mdstore_sets); 1186aace0ceSkettenis uint64_t mdstore_reqnum; 1196aace0ceSkettenis uint64_t mdstore_command; 120cceaa36bSkettenis 121cceaa36bSkettenis void 122cceaa36bSkettenis mdstore_start(struct ldc_conn *lc, uint64_t svc_handle) 123cceaa36bSkettenis { 124cceaa36bSkettenis struct mdstore_msg mm; 125cceaa36bSkettenis 126cceaa36bSkettenis bzero(&mm, sizeof(mm)); 127cceaa36bSkettenis mm.msg_type = DS_DATA; 128cceaa36bSkettenis mm.payload_len = sizeof(mm) - 8; 129cceaa36bSkettenis mm.svc_handle = svc_handle; 1306aace0ceSkettenis mm.reqnum = mdstore_reqnum++; 1316aace0ceSkettenis mm.command = mdstore_command = MDSET_LIST_REQUEST; 132cceaa36bSkettenis ds_send_msg(lc, &mm, sizeof(mm)); 133cceaa36bSkettenis } 134cceaa36bSkettenis 135cceaa36bSkettenis void 136cceaa36bSkettenis mdstore_rx_data(struct ldc_conn *lc, uint64_t svc_handle, void *data, 137cceaa36bSkettenis size_t len) 138cceaa36bSkettenis { 139cceaa36bSkettenis struct mdstore_list_resp *mr = data; 140cceaa36bSkettenis struct mdstore_set *set; 141cceaa36bSkettenis int idx; 142cceaa36bSkettenis 143cceaa36bSkettenis if (mr->result != MDST_SUCCESS) { 144cceaa36bSkettenis DPRINTF(("Unexpected result 0x%x\n", mr->result)); 145cceaa36bSkettenis return; 146cceaa36bSkettenis } 147cceaa36bSkettenis 1486aace0ceSkettenis switch (mdstore_command) { 1496aace0ceSkettenis case MDSET_LIST_REQUEST: 1506aace0ceSkettenis for (idx = 0, len = 0; len < mr->payload_len - 24; idx++) { 151cceaa36bSkettenis set = xmalloc(sizeof(*set)); 152cceaa36bSkettenis set->name = xstrdup(&mr->sets[len]); 153cceaa36bSkettenis set->booted_set = (idx == mr->booted_set); 154cceaa36bSkettenis set->boot_set = (idx == mr->boot_set); 155cceaa36bSkettenis TAILQ_INSERT_TAIL(&mdstore_sets, set, link); 156cceaa36bSkettenis len += strlen(&mr->sets[len]) + 1; 157cceaa36bSkettenis } 1586aace0ceSkettenis break; 1596aace0ceSkettenis } 160*dc8fdf3dSkettenis 161*dc8fdf3dSkettenis mdstore_command = 0; 162*dc8fdf3dSkettenis } 163*dc8fdf3dSkettenis 164*dc8fdf3dSkettenis void 165*dc8fdf3dSkettenis mdstore_begin(struct ds_conn *dc, uint64_t svc_handle, const char *name) 166*dc8fdf3dSkettenis { 167*dc8fdf3dSkettenis struct mdstore_begin_end_req *mr; 168*dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name); 169*dc8fdf3dSkettenis 170*dc8fdf3dSkettenis mr = xzalloc(len); 171*dc8fdf3dSkettenis mr->msg_type = DS_DATA; 172*dc8fdf3dSkettenis mr->payload_len = len - 8; 173*dc8fdf3dSkettenis mr->svc_handle = svc_handle; 174*dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++; 175*dc8fdf3dSkettenis mr->command = mdstore_command = MDSET_BEGIN_REQUEST; 176*dc8fdf3dSkettenis mr->nmds = 3; /* XXX */ 177*dc8fdf3dSkettenis mr->namelen = strlen(name); 178*dc8fdf3dSkettenis memcpy(mr->name, name, strlen(name)); 179*dc8fdf3dSkettenis 180*dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len); 181*dc8fdf3dSkettenis free(mr); 182*dc8fdf3dSkettenis 183*dc8fdf3dSkettenis while (mdstore_command == MDSET_BEGIN_REQUEST) 184*dc8fdf3dSkettenis ds_conn_handle(dc); 185*dc8fdf3dSkettenis } 186*dc8fdf3dSkettenis 187*dc8fdf3dSkettenis void 188*dc8fdf3dSkettenis mdstore_transfer(struct ds_conn *dc, uint64_t svc_handle, const char *path, 189*dc8fdf3dSkettenis uint16_t type, uint64_t offset) 190*dc8fdf3dSkettenis { 191*dc8fdf3dSkettenis struct mdstore_transfer_req *mr; 192*dc8fdf3dSkettenis uint32_t size; 193*dc8fdf3dSkettenis size_t len; 194*dc8fdf3dSkettenis FILE *fp; 195*dc8fdf3dSkettenis 196*dc8fdf3dSkettenis fp = fopen(path, "r"); 197*dc8fdf3dSkettenis if (fp == NULL) 198*dc8fdf3dSkettenis err(1, "fopen"); 199*dc8fdf3dSkettenis 200*dc8fdf3dSkettenis fseek(fp, 0, SEEK_END); 201*dc8fdf3dSkettenis size = ftell(fp); 202*dc8fdf3dSkettenis fseek(fp, 0, SEEK_SET); 203*dc8fdf3dSkettenis 204*dc8fdf3dSkettenis len = sizeof(*mr) + size; 205*dc8fdf3dSkettenis mr = xzalloc(len); 206*dc8fdf3dSkettenis 207*dc8fdf3dSkettenis mr->msg_type = DS_DATA; 208*dc8fdf3dSkettenis mr->payload_len = len - 8; 209*dc8fdf3dSkettenis mr->svc_handle = svc_handle; 210*dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++; 211*dc8fdf3dSkettenis mr->command = mdstore_command = MD_TRANSFER_REQUEST; 212*dc8fdf3dSkettenis mr->type = type; 213*dc8fdf3dSkettenis mr->size = size; 214*dc8fdf3dSkettenis mr->offset = offset; 215*dc8fdf3dSkettenis if (fread(&mr->md, size, 1, fp) != 1) 216*dc8fdf3dSkettenis err(1, "fread"); 217*dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len); 218*dc8fdf3dSkettenis free(mr); 219*dc8fdf3dSkettenis 220*dc8fdf3dSkettenis fclose(fp); 221*dc8fdf3dSkettenis 222*dc8fdf3dSkettenis while (mdstore_command == MD_TRANSFER_REQUEST) 223*dc8fdf3dSkettenis ds_conn_handle(dc); 224*dc8fdf3dSkettenis } 225*dc8fdf3dSkettenis 226*dc8fdf3dSkettenis void 227*dc8fdf3dSkettenis mdstore_end(struct ds_conn *dc, uint64_t svc_handle, const char *name) 228*dc8fdf3dSkettenis { 229*dc8fdf3dSkettenis struct mdstore_begin_end_req *mr; 230*dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name); 231*dc8fdf3dSkettenis 232*dc8fdf3dSkettenis mr = xzalloc(len); 233*dc8fdf3dSkettenis mr->msg_type = DS_DATA; 234*dc8fdf3dSkettenis mr->payload_len = len - 8; 235*dc8fdf3dSkettenis mr->svc_handle = svc_handle; 236*dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++; 237*dc8fdf3dSkettenis mr->command = mdstore_command = MDSET_END_REQUEST; 238*dc8fdf3dSkettenis mr->nmds = 3; 239*dc8fdf3dSkettenis mr->namelen = strlen(name); 240*dc8fdf3dSkettenis memcpy(mr->name, name, strlen(name)); 241*dc8fdf3dSkettenis 242*dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len); 243*dc8fdf3dSkettenis free(mr); 244*dc8fdf3dSkettenis 245*dc8fdf3dSkettenis while (mdstore_command == MDSET_END_REQUEST) 246*dc8fdf3dSkettenis ds_conn_handle(dc); 2476aace0ceSkettenis } 2486aace0ceSkettenis 2496aace0ceSkettenis void 2506aace0ceSkettenis mdstore_select(struct ds_conn *dc, const char *name) 2516aace0ceSkettenis { 2526aace0ceSkettenis struct ds_conn_svc *dcs; 2536aace0ceSkettenis struct mdstore_sel_del_req *mr; 254*dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name); 2556aace0ceSkettenis 2566aace0ceSkettenis TAILQ_FOREACH(dcs, &dc->services, link) 2576aace0ceSkettenis if (strcmp(dcs->service->ds_svc_id, "mdstore") == 0) 2586aace0ceSkettenis break; 2596aace0ceSkettenis assert(dcs != TAILQ_END(&dc->services)); 2606aace0ceSkettenis 2616aace0ceSkettenis mr = xzalloc(len); 2626aace0ceSkettenis mr->msg_type = DS_DATA; 2636aace0ceSkettenis mr->payload_len = len - 8; 2646aace0ceSkettenis mr->svc_handle = dcs->svc_handle; 2656aace0ceSkettenis mr->reqnum = mdstore_reqnum++; 2666aace0ceSkettenis mr->command = mdstore_command = MDSET_SELECT_REQUEST; 2676aace0ceSkettenis mr->namelen = strlen(name); 2686aace0ceSkettenis memcpy(mr->name, name, strlen(name)); 2696aace0ceSkettenis 2706aace0ceSkettenis ds_send_msg(&dc->lc, mr, len); 2716aace0ceSkettenis free(mr); 2726aace0ceSkettenis 2736aace0ceSkettenis while (mdstore_command == MDSET_SELECT_REQUEST) 2746aace0ceSkettenis ds_conn_handle(dc); 275cceaa36bSkettenis } 276*dc8fdf3dSkettenis 277*dc8fdf3dSkettenis void 278*dc8fdf3dSkettenis mdstore_delete(struct ds_conn *dc, const char *name) 279*dc8fdf3dSkettenis { 280*dc8fdf3dSkettenis struct ds_conn_svc *dcs; 281*dc8fdf3dSkettenis struct mdstore_sel_del_req *mr; 282*dc8fdf3dSkettenis size_t len = sizeof(*mr) + strlen(name); 283*dc8fdf3dSkettenis 284*dc8fdf3dSkettenis TAILQ_FOREACH(dcs, &dc->services, link) 285*dc8fdf3dSkettenis if (strcmp(dcs->service->ds_svc_id, "mdstore") == 0) 286*dc8fdf3dSkettenis break; 287*dc8fdf3dSkettenis assert(dcs != TAILQ_END(&dc->services)); 288*dc8fdf3dSkettenis 289*dc8fdf3dSkettenis mr = xzalloc(len); 290*dc8fdf3dSkettenis mr->msg_type = DS_DATA; 291*dc8fdf3dSkettenis mr->payload_len = len - 8; 292*dc8fdf3dSkettenis mr->svc_handle = dcs->svc_handle; 293*dc8fdf3dSkettenis mr->reqnum = mdstore_reqnum++; 294*dc8fdf3dSkettenis mr->command = mdstore_command = MDSET_DELETE_REQUEST; 295*dc8fdf3dSkettenis mr->namelen = strlen(name); 296*dc8fdf3dSkettenis memcpy(mr->name, name, strlen(name)); 297*dc8fdf3dSkettenis 298*dc8fdf3dSkettenis ds_send_msg(&dc->lc, mr, len); 299*dc8fdf3dSkettenis free(mr); 300*dc8fdf3dSkettenis 301*dc8fdf3dSkettenis while (mdstore_command == MDSET_DELETE_REQUEST) 302*dc8fdf3dSkettenis ds_conn_handle(dc); 303*dc8fdf3dSkettenis } 304*dc8fdf3dSkettenis 305*dc8fdf3dSkettenis void 306*dc8fdf3dSkettenis mdstore_download(struct ds_conn *dc, const char *name) 307*dc8fdf3dSkettenis { 308*dc8fdf3dSkettenis struct ds_conn_svc *dcs; 309*dc8fdf3dSkettenis 310*dc8fdf3dSkettenis TAILQ_FOREACH(dcs, &dc->services, link) 311*dc8fdf3dSkettenis if (strcmp(dcs->service->ds_svc_id, "mdstore") == 0) 312*dc8fdf3dSkettenis break; 313*dc8fdf3dSkettenis assert(dcs != TAILQ_END(&dc->services)); 314*dc8fdf3dSkettenis 315*dc8fdf3dSkettenis printf("begin\n"); 316*dc8fdf3dSkettenis mdstore_begin(dc, dcs->svc_handle, name); 317*dc8fdf3dSkettenis printf("transfer 0\n"); 318*dc8fdf3dSkettenis mdstore_transfer(dc, dcs->svc_handle, "primary.md", 319*dc8fdf3dSkettenis MDSTORE_CTL_DOM_MD_TYPE, 0x100000); 320*dc8fdf3dSkettenis printf("transfer 1\n"); 321*dc8fdf3dSkettenis mdstore_transfer(dc, dcs->svc_handle, "hv.md", 322*dc8fdf3dSkettenis MDSTORE_HV_MD_TYPE, 0x80000); 323*dc8fdf3dSkettenis printf("transfer 2\n"); 324*dc8fdf3dSkettenis mdstore_transfer(dc, dcs->svc_handle, "pri", 325*dc8fdf3dSkettenis MDSTORE_PRI_TYPE, 0); 326*dc8fdf3dSkettenis printf("end\n"); 327*dc8fdf3dSkettenis mdstore_end(dc, dcs->svc_handle, name); 328*dc8fdf3dSkettenis printf("done\n"); 329*dc8fdf3dSkettenis } 330