1 /* 2 * Copyright (c) 2023, Google Inc. All rights reserved. 3 * Author: codycswong@google.com (Cody Wong) 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files 7 * (the "Software"), to deal in the Software without restriction, 8 * including without limitation the rights to use, copy, modify, merge, 9 * publish, distribute, sublicense, and/or sell copies of the Software, 10 * and to permit persons to whom the Software is furnished to do so, 11 * subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be 14 * included in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 #pragma once 25 26 #include <dev/virtio.h> 27 #include <lib/bio.h> 28 #include <lk/compiler.h> 29 #include <kernel/spinlock.h> 30 #include <sys/types.h> 31 32 #define VIRTIO_9P_RING_IDX 0 33 #define VIRTIO_9P_RING_SIZE 128 34 35 // Assuming there can be only one outstanding request. Pick a 16-bit unsigned 36 // value arbtrarily as the default tag for no good reason. 37 #define P9_TAG_DEFAULT ((uint16_t)0x15) 38 #define P9_TAG_NOTAG ((uint16_t)~0) 39 40 #define P9_FID_NOFID ((uint32_t)~0) 41 42 #define P9_UNAME_NONUNAME ((uint32_t)~0) 43 44 #define P9_MAXWELEM 16 45 46 #ifdef V9P_HOST_DIR 47 #define V9P_MOUNT_ANAME V9P_HOST_DIR 48 #else 49 #define V9P_MOUNT_ANAME "" 50 #endif // V9P_MOUNT_ANAME 51 52 // Linux file flags 53 #define O_RDONLY 00000000 54 #define O_WRONLY 00000001 55 #define O_RDWR 00000002 56 #ifndef O_CREAT 57 #define O_CREAT 00000100 58 #endif 59 #ifndef O_EXCL 60 #define O_EXCL 00000200 61 #endif 62 #ifndef O_NOCTTY 63 #define O_NOCTTY 00000400 64 #endif 65 #ifndef O_TRUNC 66 #define O_TRUNC 00001000 67 #endif 68 #ifndef O_APPEND 69 #define O_APPEND 00002000 70 #endif 71 #ifndef O_NONBLOCK 72 #define O_NONBLOCK 00004000 73 #endif 74 #ifndef O_DSYNC 75 #define O_DSYNC 00010000 76 #endif 77 #ifndef FASYNC 78 #define FASYNC 00020000 79 #endif 80 #ifndef O_DIRECT 81 #define O_DIRECT 00040000 82 #endif 83 #ifndef O_LARGEFILE 84 #define O_LARGEFILE 00100000 85 #endif 86 #ifndef O_DIRECTORY 87 #define O_DIRECTORY 00200000 88 #endif 89 #ifndef O_NOFOLLOW 90 #define O_NOFOLLOW 00400000 91 #endif 92 #ifndef O_NOATIME 93 #define O_NOATIME 01000000 94 #endif 95 #ifndef O_CLOEXEC 96 #define O_CLOEXEC 02000000 97 #endif 98 99 // POSIX file modes 100 #define S_IRWXU 00700 // user (file owner) has read, write, and execute permission 101 #define S_IRUSR 00400 // user has read permission 102 #define S_IWUSR 00200 // user has write permission 103 #define S_IXUSR 00100 // user has execute permission 104 #define S_IRWXG 00070 // group has read, write, and execute permission 105 #define S_IRGRP 00040 // group has read permission 106 #define S_IWGRP 00020 // group has write permission 107 #define S_IXGRP 00010 // group has execute permission 108 #define S_IRWXO 00007 // others have read, write, and execute permission 109 #define S_IROTH 00004 // others have read permission 110 #define S_IWOTH 00002 // others have write permission 111 #define S_IXOTH 00001 // others have execute permission 112 /* According to POSIX, the effect when other bits are set in mode is 113 * unspecified. On Linux, the following bits are also honored in mode: */ 114 #define S_ISUID 0004000 // set-user-ID bit 115 #define S_ISGID 0002000 // set-group-ID bit (see inode(7)). 116 #define S_ISVTX 0001000 // sticky bit (see inode(7)). 117 118 // Linux file modes 119 #define S_IFMT 00170000 120 #define S_IFSOCK 0140000 121 #define S_IFLNK 0120000 122 #define S_IFREG 0100000 123 #define S_IFBLK 0060000 124 #define S_IFDIR 0040000 125 #define S_IFCHR 0020000 126 #define S_IFIFO 0010000 127 #define S_ISUID 0004000 128 #define S_ISGID 0002000 129 #define S_ISVTX 0001000 130 131 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) 132 #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) 133 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) 134 #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) 135 #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) 136 #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) 137 #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) 138 139 #define P9_GETATTR_MODE 0x00000001ULL 140 #define P9_GETATTR_NLINK 0x00000002ULL 141 #define P9_GETATTR_UID 0x00000004ULL 142 #define P9_GETATTR_GID 0x00000008ULL 143 #define P9_GETATTR_RDEV 0x00000010ULL 144 #define P9_GETATTR_ATIME 0x00000020ULL 145 #define P9_GETATTR_MTIME 0x00000040ULL 146 #define P9_GETATTR_CTIME 0x00000080ULL 147 #define P9_GETATTR_INO 0x00000100ULL 148 #define P9_GETATTR_SIZE 0x00000200ULL 149 #define P9_GETATTR_BLOCKS 0x00000400ULL 150 151 #define P9_GETATTR_BTIME 0x00000800ULL 152 #define P9_GETATTR_GEN 0x00001000ULL 153 #define P9_GETATTR_DATA_VERSION 0x00002000ULL 154 155 #define P9_GETATTR_BASIC 0x000007ffULL /* Mask for fields up to BLOCKS */ 156 #define P9_GETATTR_ALL 0x00003fffULL /* Mask for All fields above */ 157 158 enum virtio_9p_msg_type_t { 159 P9_TLERROR = 6, 160 P9_RLERROR, 161 P9_TSTATFS = 8, 162 P9_RSTATFS, 163 P9_TLOPEN = 12, 164 P9_RLOPEN, 165 P9_TLCREATE = 14, 166 P9_RLCREATE, 167 P9_TSYMLINK = 16, 168 P9_RSYMLINK, 169 P9_TMKNOD = 18, 170 P9_RMKNOD, 171 P9_TRENAME = 20, 172 P9_RRENAME, 173 P9_TREADLINK = 22, 174 P9_RREADLINK, 175 P9_TGETATTR = 24, 176 P9_RGETATTR, 177 P9_TSETATTR = 26, 178 P9_RSETATTR, 179 P9_TXATTRWALK = 30, 180 P9_RXATTRWALK, 181 P9_TXATTRCREATE = 32, 182 P9_RXATTRCREATE, 183 P9_TREADDIR = 40, 184 P9_RREADDIR, 185 P9_TFSYNC = 50, 186 P9_RFSYNC, 187 P9_TLOCK = 52, 188 P9_RLOCK, 189 P9_TGETLOCK = 54, 190 P9_RGETLOCK, 191 P9_TLINK = 70, 192 P9_RLINK, 193 P9_TMKDIR = 72, 194 P9_RMKDIR, 195 P9_TRENAMEAT = 74, 196 P9_RRENAMEAT, 197 P9_TUNLINKAT = 76, 198 P9_RUNLINKAT, 199 P9_TVERSION = 100, 200 P9_RVERSION, 201 P9_TAUTH = 102, 202 P9_RAUTH, 203 P9_TATTACH = 104, 204 P9_RATTACH, 205 P9_TERROR = 106, 206 P9_RERROR, 207 P9_TFLUSH = 108, 208 P9_RFLUSH, 209 P9_TWALK = 110, 210 P9_RWALK, 211 P9_TOPEN = 112, 212 P9_ROPEN, 213 P9_TCREATE = 114, 214 P9_RCREATE, 215 P9_TREAD = 116, 216 P9_RREAD, 217 P9_TWRITE = 118, 218 P9_RWRITE, 219 P9_TCLUNK = 120, 220 P9_RCLUNK, 221 P9_TREMOVE = 122, 222 P9_RREMOVE, 223 P9_TSTAT = 124, 224 P9_RSTAT, 225 P9_TWSTAT = 126, 226 P9_RWSTAT, 227 }; 228 229 typedef struct _virtio_9p_qid_t { 230 uint8_t type; 231 uint32_t version; 232 uint64_t path; 233 } virtio_9p_qid_t; 234 235 enum p9_qid_t { 236 P9_QTDIR = 0x80, 237 P9_QTAPPEND = 0x40, 238 P9_QTEXCL = 0x20, 239 P9_QTMOUNT = 0x10, 240 P9_QTAUTH = 0x08, 241 P9_QTTMP = 0x04, 242 P9_QTSYMLINK = 0x02, 243 P9_QTLINK = 0x01, 244 P9_QTFILE = 0x00, 245 }; 246 247 typedef struct p9_dirent { 248 virtio_9p_qid_t qid; 249 uint64_t offset; 250 uint8_t type; 251 char *name; 252 } p9_dirent_t; 253 254 typedef struct _virtio_9p_msg_t { 255 enum virtio_9p_msg_type_t msg_type; 256 uint16_t tag; 257 258 // the 9p message structures supporting 9P2000.L 259 union { 260 // Tlerror 261 // Rlerror 262 struct { 263 uint32_t ecode; 264 } rlerror; 265 266 // Tlopen 267 struct { 268 uint32_t fid; 269 uint32_t flags; 270 } tlopen; 271 // Rlopen 272 struct { 273 virtio_9p_qid_t qid; 274 uint32_t iounit; 275 } rlopen; 276 277 // Tlcreate 278 struct { 279 uint32_t fid; 280 const char *name; 281 uint32_t flags; 282 uint32_t mode; 283 uint32_t gid; 284 } tlcreate; 285 // Rlcreate 286 struct { 287 virtio_9p_qid_t qid; 288 uint32_t iounit; 289 } rlcreate; 290 291 // Tgetattr 292 struct { 293 uint32_t fid; 294 uint64_t request_mask; 295 } tgetattr; 296 // Rgetattr 297 struct { 298 uint64_t valid; 299 virtio_9p_qid_t qid; 300 uint32_t mode; 301 uint32_t uid; 302 uint32_t gid; 303 uint64_t nlink; 304 uint64_t rdev; 305 uint64_t size; 306 uint64_t blksize; 307 uint64_t blocks; 308 uint64_t atime_sec; 309 uint64_t atime_nsec; 310 uint64_t mtime_sec; 311 uint64_t mtime_nsec; 312 uint64_t ctime_sec; 313 uint64_t ctime_nsec; 314 uint64_t btime_sec; 315 uint64_t btime_nsec; 316 uint64_t gen; 317 uint64_t data_version; 318 } rgetattr; 319 320 // Tversion 321 struct { 322 uint32_t msize; 323 const char *version; 324 } tversion; 325 // Rversion 326 struct { 327 uint32_t msize; 328 char *version; 329 } rversion; 330 331 // Tauth 332 // Rauth 333 334 // Rerror 335 336 // Tflush 337 // Rflush 338 339 // Tattach 340 struct { 341 uint32_t fid; 342 uint32_t afid; 343 const char *uname; 344 const char *aname; 345 uint32_t n_uname; 346 } tattach; 347 // Rattach 348 struct { 349 virtio_9p_qid_t qid; 350 } rattach; 351 352 // Twalk 353 struct { 354 uint32_t fid; 355 uint32_t newfid; 356 uint16_t nwname; 357 const char *wname[P9_MAXWELEM]; 358 } twalk; 359 // Rwalk 360 struct { 361 uint16_t nwqid; 362 virtio_9p_qid_t qid[P9_MAXWELEM]; 363 } rwalk; 364 365 // Topen 366 struct { 367 uint32_t fid; 368 uint8_t mode; 369 } topen; 370 // Ropen 371 struct { 372 virtio_9p_qid_t qid; 373 uint32_t iounit; 374 } ropen; 375 376 // Tcreate 377 // Rcreate 378 379 // Tread 380 struct { 381 uint32_t fid; 382 uint64_t offset; 383 uint32_t count; 384 } tread; 385 // Rread 386 struct { 387 uint32_t count; 388 uint8_t *data; 389 } rread; 390 391 // Twrite 392 struct { 393 uint32_t fid; 394 uint64_t offset; 395 uint32_t count; 396 const uint8_t *data; 397 } twrite; 398 // Rwrite 399 struct { 400 uint32_t count; 401 } rwrite; 402 403 // Tclunk 404 struct { 405 uint32_t fid; 406 } tclunk; 407 // Rclunk 408 struct { 409 } rclunk; 410 411 // Tremove 412 struct { 413 uint32_t fid; 414 } tremove; 415 // Rremove 416 struct { 417 } rremove; 418 419 // Tstat 420 // Rstat 421 422 // Twstat 423 // Rwstat 424 425 // Treaddir 426 struct { 427 uint32_t fid; 428 uint64_t offset; 429 uint32_t count; 430 } treaddir; 431 // Rreaddir 432 struct { 433 uint32_t count; 434 uint8_t *data; 435 } rreaddir; 436 437 // Tmkdir 438 struct { 439 uint32_t dfid; 440 const char *name; 441 uint32_t mode; 442 uint32_t gid; 443 } tmkdir; 444 // Rmkdir 445 struct { 446 virtio_9p_qid_t qid; 447 } rmkdir; 448 } msg; 449 450 } virtio_9p_msg_t; 451 452 status_t virtio_9p_init(struct virtio_device *dev, uint32_t host_features) __NONNULL(); 453 status_t virtio_9p_start(struct virtio_device *dev) __NONNULL(); 454 struct virtio_device *virtio_9p_bdev_to_virtio_device(bdev_t *bdev); 455 struct virtio_device *virtio_get_9p_device(uint index); 456 457 status_t virtio_9p_rpc(struct virtio_device *dev, const virtio_9p_msg_t *tmsg, 458 virtio_9p_msg_t *rmsg); 459 void virtio_9p_msg_destroy(virtio_9p_msg_t *msg); 460 ssize_t p9_dirent_read(uint8_t *data, uint32_t size, p9_dirent_t *ent); 461 void p9_dirent_destroy(p9_dirent_t *ent); 462