1 /* ProcFS - service.c - the service subdirectory */ 2 3 #include "inc.h" 4 5 #include <minix/rs.h> 6 #include "rs/const.h" 7 #include "rs/type.h" 8 9 enum policy { 10 POL_NONE = 0x00, /* user | endpoint */ 11 POL_RESET = 0x01, /* visible | change */ 12 POL_RESTART = 0x02, /* transparent | preserved */ 13 POL_LIVE_UPDATE = 0x04 /* transparent | preserved */ 14 }; 15 16 struct policies { 17 #define MAX_POL_FORMAT_SZ 20 18 char formatted[MAX_POL_FORMAT_SZ]; 19 enum policy supported; 20 }; 21 22 static struct rprocpub rprocpub[NR_SYS_PROCS]; 23 static struct rproc rproc[NR_SYS_PROCS]; 24 static struct policies policies[NR_SYS_PROCS]; 25 26 static struct inode *service_node; 27 28 /* Updates the policies state from RS. Always returns an ASCIIZ string. */ 29 static const char * 30 service_get_policies(struct policies * pol, index_t slot) 31 { 32 #if 1 /* The following should be retrieved from RS and formated instead. */ 33 int pos; 34 char *ref_label; 35 static const struct { 36 const char *label; 37 const char *policy_str; 38 } def_pol[] = { 39 /* audio */ 40 { .label = "es1370", .policy_str = "reset" }, 41 { .label = "es1371", .policy_str = "reset" }, 42 { .label = "sb16", .policy_str = "reset" }, 43 /* bus */ 44 { .label = "i2c", .policy_str = "restart" }, 45 { .label = "pci", .policy_str = "restart" }, 46 { .label = "ti1225", .policy_str = "restart" }, 47 /* clock */ 48 { .label = "readclock.drv", .policy_str = "restart" }, 49 /* eeprom */ 50 { .label = "cat24c256", .policy_str = "restart" }, 51 /* examples */ 52 { .label = "hello", .policy_str = "restart" }, 53 /* hid */ 54 { .label = "pckbd", .policy_str = "reset" }, 55 /* iommu */ 56 { .label = "amddev", .policy_str = "" }, 57 /* net */ 58 { .label = "3c90x", .policy_str = "restart" }, 59 { .label = "atl2", .policy_str = "restart" }, 60 { .label = "dec21140A", .policy_str = "restart" }, 61 { .label = "dp8390", .policy_str = "restart" }, 62 { .label = "dpeth", .policy_str = "restart" }, 63 { .label = "e1000", .policy_str = "restart" }, 64 { .label = "fxp", .policy_str = "restart" }, 65 { .label = "lance", .policy_str = "restart" }, 66 { .label = "lan8710a", .policy_str = "restart" }, 67 { .label = "orinoco", .policy_str = "restart" }, 68 { .label = "rtl8139", .policy_str = "restart" }, 69 { .label = "rtl8169", .policy_str = "restart" }, 70 { .label = "uds", .policy_str = "reset" }, 71 { .label = "virtio_net", .policy_str = "restart" }, 72 /* power */ 73 { .label = "acpi", .policy_str = "" }, 74 { .label = "tps65217", .policy_str = "" }, 75 { .label = "tps65590", .policy_str = "" }, 76 /* printer */ 77 { .label = "printer", .policy_str = "restart" }, 78 /* sensors */ 79 { .label = "bmp085", .policy_str = "" }, 80 { .label = "sht21", .policy_str = "restart" }, 81 { .label = "tsl2550", .policy_str = "restart" }, 82 /* storage */ 83 { .label = "ahci", .policy_str = "reset" }, 84 { .label = "at_wini", .policy_str = "reset" }, 85 { .label = "fbd", .policy_str = "reset" }, 86 { .label = "filter", .policy_str = "reset" }, 87 { .label = "floppy", .policy_str = "reset" }, 88 { .label = "memory", .policy_str = "restart" }, 89 { .label = "mmc", .policy_str = "reset" }, 90 { .label = "virtio_blk", .policy_str = "reset" }, 91 { .label = "vnd", .policy_str = "reset" }, 92 /* system */ 93 { .label = "gpio", .policy_str = "restart" }, 94 { .label = "log", .policy_str = "restart" }, 95 { .label = "random", .policy_str = "restart" }, 96 /* tty */ 97 { .label = "pty", .policy_str = "restart" }, 98 { .label = "tty", .policy_str = "" }, 99 /* usb */ 100 { .label = "usbd", .policy_str = "" }, 101 { .label = "usb_hub", .policy_str = "" }, 102 { .label = "usb_storage", .policy_str = "" }, 103 /* video */ 104 { .label = "fb", .policy_str = "" }, 105 { .label = "tda19988", .policy_str = "" }, 106 /* vmm_guest */ 107 { .label = "vbox", .policy_str = "" }, 108 /* fs */ 109 { .label = "ext2", .policy_str = "" }, 110 { .label = "hgfs", .policy_str = "" }, 111 { .label = "isofs", .policy_str = "" }, 112 { .label = "mfs", .policy_str = "" }, 113 { .label = "pfs", .policy_str = "" }, 114 { .label = "procfs", .policy_str = "" }, 115 { .label = "vbfs", .policy_str = "" }, 116 /* net */ 117 { .label = "inet", .policy_str = "reset" }, 118 { .label = "lwip", .policy_str = "" }, 119 /* servers */ 120 { .label = "devman", .policy_str = "" }, 121 { .label = "ds", .policy_str = "" }, 122 { .label = "input", .policy_str = "reset" }, 123 { .label = "ipc", .policy_str = "restart" }, 124 { .label = "is", .policy_str = "restart" }, 125 { .label = "pm", .policy_str = "" }, 126 { .label = "rs", .policy_str = "" }, 127 { .label = "sched", .policy_str = "" }, 128 { .label = "vfs", .policy_str = "" }, 129 { .label = "vm", .policy_str = "" }, 130 //{ .label = "", .policy_str = "" }, 131 }; 132 133 /* Find the related policy, based on the file name of the service. */ 134 ref_label = strrchr(rprocpub[slot].proc_name, '/'); 135 if (NULL == ref_label) 136 ref_label = rprocpub[slot].proc_name; 137 138 memset(pol[slot].formatted, 0, MAX_POL_FORMAT_SZ); 139 for(pos = 0; pos < (sizeof(def_pol) / sizeof(def_pol[0])); pos++) { 140 if (0 == strcmp(ref_label, def_pol[pos].label)) { 141 (void)strncpy(pol[slot].formatted, def_pol[pos].policy_str, MAX_POL_FORMAT_SZ); 142 pol[slot].formatted[MAX_POL_FORMAT_SZ-1] = '\0'; 143 break; 144 } 145 } 146 #else 147 /* Should do something sensible, based on flags from RS/SEF. */ 148 #endif 149 150 return pol[slot].formatted; 151 } 152 153 /* 154 * Update the contents of the service directory, by first updating the RS 155 * tables and then updating the directory contents. 156 */ 157 static void 158 service_update(void) 159 { 160 struct inode *node; 161 struct inode_stat stat; 162 index_t slot; 163 164 /* There is not much we can do if either of these calls fails. */ 165 (void)getsysinfo(RS_PROC_NR, SI_PROCPUB_TAB, rprocpub, 166 sizeof(rprocpub)); 167 (void)getsysinfo(RS_PROC_NR, SI_PROC_TAB, rproc, sizeof(rproc)); 168 169 /* 170 * As with PIDs, we make two passes. Delete first, then add. This 171 * prevents problems in the hypothetical case that between updates, one 172 * slot ends up with the label name of a previous, different slot. 173 */ 174 for (slot = 0; slot < NR_SYS_PROCS; slot++) { 175 if ((node = get_inode_by_index(service_node, slot)) == NULL) 176 continue; 177 178 /* 179 * If the slot is no longer in use, or the label name does not 180 * match, the node must be deleted. 181 */ 182 if (!(rproc[slot].r_flags & RS_IN_USE) || 183 strcmp(get_inode_name(node), rprocpub[slot].label)) 184 delete_inode(node); 185 } 186 187 memset(&stat, 0, sizeof(stat)); 188 stat.mode = REG_ALL_MODE; 189 stat.uid = SUPER_USER; 190 stat.gid = SUPER_USER; 191 192 for (slot = 0; slot < NR_SYS_PROCS; slot++) { 193 if (!(rproc[slot].r_flags & RS_IN_USE) || 194 get_inode_by_index(service_node, slot) != NULL) 195 continue; 196 197 node = add_inode(service_node, rprocpub[slot].label, slot, 198 &stat, (index_t)0, (cbdata_t)slot); 199 200 if (node == NULL) 201 out_of_inodes(); 202 } 203 } 204 205 /* 206 * Initialize the service directory. 207 */ 208 void 209 service_init(void) 210 { 211 struct inode *root, *node; 212 struct inode_stat stat; 213 214 root = get_root_inode(); 215 216 memset(&stat, 0, sizeof(stat)); 217 stat.mode = DIR_ALL_MODE; 218 stat.uid = SUPER_USER; 219 stat.gid = SUPER_USER; 220 221 service_node = add_inode(root, "service", NO_INDEX, &stat, 222 NR_SYS_PROCS, NULL); 223 224 if (service_node == NULL) 225 panic("unable to create service node"); 226 } 227 228 /* 229 * A lookup request is being performed. If it is in the service directory, 230 * update the tables. We do this lazily, to reduce overhead. 231 */ 232 void 233 service_lookup(struct inode * parent, clock_t now) 234 { 235 static clock_t last_update = 0; 236 237 if (parent != service_node) 238 return; 239 240 if (last_update != now) { 241 service_update(); 242 243 last_update = now; 244 } 245 } 246 247 /* 248 * A getdents request is being performed. If it is in the service directory, 249 * update the tables. 250 */ 251 void 252 service_getdents(struct inode * node) 253 { 254 255 if (node != service_node) 256 return; 257 258 service_update(); 259 } 260 261 /* 262 * A read request is being performed. If it is on a file in the service 263 * directory, process the read request. We rely on the fact that any read 264 * call will have been preceded by a lookup, so its table entry has been 265 * updated very recently. 266 */ 267 void 268 service_read(struct inode * node) 269 { 270 struct inode *parent; 271 index_t slot; 272 struct rprocpub *rpub; 273 struct rproc *rp; 274 275 if (get_parent_inode(node) != service_node) 276 return; 277 278 slot = get_inode_index(node); 279 rpub = &rprocpub[slot]; 280 rp = &rproc[slot]; 281 282 /* TODO: add a large number of other fields! */ 283 buf_printf("filename: %s\n", rpub->proc_name); 284 buf_printf("endpoint: %d\n", rpub->endpoint); 285 buf_printf("restarts: %d\n", rp->r_restarts); 286 buf_printf("policies: %s\n", service_get_policies(policies, slot)); 287 } 288