efi_file.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * EFI_FILE_PROTOCOL
  4. *
  5. * Copyright (c) 2017 Rob Clark
  6. */
  7. #include <common.h>
  8. #include <charset.h>
  9. #include <efi_loader.h>
  10. #include <malloc.h>
  11. #include <mapmem.h>
  12. #include <fs.h>
  13. #include <part.h>
  14. /* GUID for file system information */
  15. const efi_guid_t efi_file_system_info_guid = EFI_FILE_SYSTEM_INFO_GUID;
  16. /* GUID to obtain the volume label */
  17. const efi_guid_t efi_system_volume_label_id = EFI_FILE_SYSTEM_VOLUME_LABEL_ID;
  18. struct file_system {
  19. struct efi_simple_file_system_protocol base;
  20. struct efi_device_path *dp;
  21. struct blk_desc *desc;
  22. int part;
  23. };
  24. #define to_fs(x) container_of(x, struct file_system, base)
  25. struct file_handle {
  26. struct efi_file_handle base;
  27. struct file_system *fs;
  28. loff_t offset; /* current file position/cursor */
  29. int isdir;
  30. u64 open_mode;
  31. /* for reading a directory: */
  32. struct fs_dir_stream *dirs;
  33. struct fs_dirent *dent;
  34. char path[0];
  35. };
  36. #define to_fh(x) container_of(x, struct file_handle, base)
  37. static const struct efi_file_handle efi_file_handle_protocol;
  38. static char *basename(struct file_handle *fh)
  39. {
  40. char *s = strrchr(fh->path, '/');
  41. if (s)
  42. return s + 1;
  43. return fh->path;
  44. }
  45. static int set_blk_dev(struct file_handle *fh)
  46. {
  47. return fs_set_blk_dev_with_part(fh->fs->desc, fh->fs->part);
  48. }
  49. /**
  50. * is_dir() - check if file handle points to directory
  51. *
  52. * We assume that set_blk_dev(fh) has been called already.
  53. *
  54. * @fh: file handle
  55. * Return: true if file handle points to a directory
  56. */
  57. static int is_dir(struct file_handle *fh)
  58. {
  59. struct fs_dir_stream *dirs;
  60. dirs = fs_opendir(fh->path);
  61. if (!dirs)
  62. return 0;
  63. fs_closedir(dirs);
  64. return 1;
  65. }
  66. /*
  67. * Normalize a path which may include either back or fwd slashes,
  68. * double slashes, . or .. entries in the path, etc.
  69. */
  70. static int sanitize_path(char *path)
  71. {
  72. char *p;
  73. /* backslash to slash: */
  74. p = path;
  75. while ((p = strchr(p, '\\')))
  76. *p++ = '/';
  77. /* handle double-slashes: */
  78. p = path;
  79. while ((p = strstr(p, "//"))) {
  80. char *src = p + 1;
  81. memmove(p, src, strlen(src) + 1);
  82. }
  83. /* handle extra /.'s */
  84. p = path;
  85. while ((p = strstr(p, "/."))) {
  86. /*
  87. * You'd be tempted to do this *after* handling ".."s
  88. * below to avoid having to check if "/." is start of
  89. * a "/..", but that won't have the correct results..
  90. * for example, "/foo/./../bar" would get resolved to
  91. * "/foo/bar" if you did these two passes in the other
  92. * order
  93. */
  94. if (p[2] == '.') {
  95. p += 2;
  96. continue;
  97. }
  98. char *src = p + 2;
  99. memmove(p, src, strlen(src) + 1);
  100. }
  101. /* handle extra /..'s: */
  102. p = path;
  103. while ((p = strstr(p, "/.."))) {
  104. char *src = p + 3;
  105. p--;
  106. /* find beginning of previous path entry: */
  107. while (true) {
  108. if (p < path)
  109. return -1;
  110. if (*p == '/')
  111. break;
  112. p--;
  113. }
  114. memmove(p, src, strlen(src) + 1);
  115. }
  116. return 0;
  117. }
  118. /**
  119. * efi_create_file() - create file or directory
  120. *
  121. * @fh: file handle
  122. * @attributes: attributes for newly created file
  123. * Returns: 0 for success
  124. */
  125. static int efi_create_file(struct file_handle *fh, u64 attributes)
  126. {
  127. loff_t actwrite;
  128. void *buffer = &actwrite;
  129. if (attributes & EFI_FILE_DIRECTORY)
  130. return fs_mkdir(fh->path);
  131. else
  132. return fs_write(fh->path, map_to_sysmem(buffer), 0, 0,
  133. &actwrite);
  134. }
  135. /**
  136. * file_open() - open a file handle
  137. *
  138. * @fs: file system
  139. * @parent: directory relative to which the file is to be opened
  140. * @file_name: path of the file to be opened. '\', '.', or '..' may
  141. * be used as modifiers. A leading backslash indicates an
  142. * absolute path.
  143. * @open_mode: bit mask indicating the access mode (read, write,
  144. * create)
  145. * @attributes: attributes for newly created file
  146. * Returns: handle to the opened file or NULL
  147. */
  148. static struct efi_file_handle *file_open(struct file_system *fs,
  149. struct file_handle *parent, u16 *file_name, u64 open_mode,
  150. u64 attributes)
  151. {
  152. struct file_handle *fh;
  153. char f0[MAX_UTF8_PER_UTF16] = {0};
  154. int plen = 0;
  155. int flen = 0;
  156. if (file_name) {
  157. utf16_to_utf8((u8 *)f0, file_name, 1);
  158. flen = u16_strlen(file_name);
  159. }
  160. /* we could have a parent, but also an absolute path: */
  161. if (f0[0] == '\\') {
  162. plen = 0;
  163. } else if (parent) {
  164. plen = strlen(parent->path) + 1;
  165. }
  166. /* +2 is for null and '/' */
  167. fh = calloc(1, sizeof(*fh) + plen + (flen * MAX_UTF8_PER_UTF16) + 2);
  168. fh->open_mode = open_mode;
  169. fh->base = efi_file_handle_protocol;
  170. fh->fs = fs;
  171. if (parent) {
  172. char *p = fh->path;
  173. int exists;
  174. if (plen > 0) {
  175. strcpy(p, parent->path);
  176. p += plen - 1;
  177. *p++ = '/';
  178. }
  179. utf16_to_utf8((u8 *)p, file_name, flen);
  180. if (sanitize_path(fh->path))
  181. goto error;
  182. /* check if file exists: */
  183. if (set_blk_dev(fh))
  184. goto error;
  185. exists = fs_exists(fh->path);
  186. /* fs_exists() calls fs_close(), so open file system again */
  187. if (set_blk_dev(fh))
  188. goto error;
  189. if (!exists) {
  190. if (!(open_mode & EFI_FILE_MODE_CREATE) ||
  191. efi_create_file(fh, attributes))
  192. goto error;
  193. if (set_blk_dev(fh))
  194. goto error;
  195. }
  196. /* figure out if file is a directory: */
  197. fh->isdir = is_dir(fh);
  198. } else {
  199. fh->isdir = 1;
  200. strcpy(fh->path, "");
  201. }
  202. return &fh->base;
  203. error:
  204. free(fh);
  205. return NULL;
  206. }
  207. static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file,
  208. struct efi_file_handle **new_handle,
  209. u16 *file_name, u64 open_mode, u64 attributes)
  210. {
  211. struct file_handle *fh = to_fh(file);
  212. efi_status_t ret;
  213. EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", file, new_handle,
  214. file_name, open_mode, attributes);
  215. /* Check parameters */
  216. if (!file || !new_handle || !file_name) {
  217. ret = EFI_INVALID_PARAMETER;
  218. goto out;
  219. }
  220. if (open_mode != EFI_FILE_MODE_READ &&
  221. open_mode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE) &&
  222. open_mode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
  223. EFI_FILE_MODE_CREATE)) {
  224. ret = EFI_INVALID_PARAMETER;
  225. goto out;
  226. }
  227. /*
  228. * The UEFI spec requires that attributes are only set in create mode.
  229. * The SCT does not care about this and sets EFI_FILE_DIRECTORY in
  230. * read mode. EDK2 does not check that attributes are zero if not in
  231. * create mode.
  232. *
  233. * So here we only check attributes in create mode and do not check
  234. * that they are zero otherwise.
  235. */
  236. if ((open_mode & EFI_FILE_MODE_CREATE) &&
  237. (attributes & (EFI_FILE_READ_ONLY | ~EFI_FILE_VALID_ATTR))) {
  238. ret = EFI_INVALID_PARAMETER;
  239. goto out;
  240. }
  241. /* Open file */
  242. *new_handle = file_open(fh->fs, fh, file_name, open_mode, attributes);
  243. if (*new_handle) {
  244. EFI_PRINT("file handle %p\n", *new_handle);
  245. ret = EFI_SUCCESS;
  246. } else {
  247. ret = EFI_NOT_FOUND;
  248. }
  249. out:
  250. return EFI_EXIT(ret);
  251. }
  252. static efi_status_t file_close(struct file_handle *fh)
  253. {
  254. fs_closedir(fh->dirs);
  255. free(fh);
  256. return EFI_SUCCESS;
  257. }
  258. static efi_status_t EFIAPI efi_file_close(struct efi_file_handle *file)
  259. {
  260. struct file_handle *fh = to_fh(file);
  261. EFI_ENTRY("%p", file);
  262. return EFI_EXIT(file_close(fh));
  263. }
  264. static efi_status_t EFIAPI efi_file_delete(struct efi_file_handle *file)
  265. {
  266. struct file_handle *fh = to_fh(file);
  267. efi_status_t ret = EFI_SUCCESS;
  268. EFI_ENTRY("%p", file);
  269. if (set_blk_dev(fh) || fs_unlink(fh->path))
  270. ret = EFI_WARN_DELETE_FAILURE;
  271. file_close(fh);
  272. return EFI_EXIT(ret);
  273. }
  274. /**
  275. * efi_get_file_size() - determine the size of a file
  276. *
  277. * @fh: file handle
  278. * @file_size: pointer to receive file size
  279. * Return: status code
  280. */
  281. static efi_status_t efi_get_file_size(struct file_handle *fh,
  282. loff_t *file_size)
  283. {
  284. if (set_blk_dev(fh))
  285. return EFI_DEVICE_ERROR;
  286. if (fs_size(fh->path, file_size))
  287. return EFI_DEVICE_ERROR;
  288. return EFI_SUCCESS;
  289. }
  290. static efi_status_t file_read(struct file_handle *fh, u64 *buffer_size,
  291. void *buffer)
  292. {
  293. loff_t actread;
  294. efi_status_t ret;
  295. loff_t file_size;
  296. ret = efi_get_file_size(fh, &file_size);
  297. if (ret != EFI_SUCCESS)
  298. return ret;
  299. if (file_size < fh->offset) {
  300. ret = EFI_DEVICE_ERROR;
  301. return ret;
  302. }
  303. if (set_blk_dev(fh))
  304. return EFI_DEVICE_ERROR;
  305. if (fs_read(fh->path, map_to_sysmem(buffer), fh->offset,
  306. *buffer_size, &actread))
  307. return EFI_DEVICE_ERROR;
  308. *buffer_size = actread;
  309. fh->offset += actread;
  310. return EFI_SUCCESS;
  311. }
  312. static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size,
  313. void *buffer)
  314. {
  315. struct efi_file_info *info = buffer;
  316. struct fs_dirent *dent;
  317. u64 required_size;
  318. u16 *dst;
  319. if (set_blk_dev(fh))
  320. return EFI_DEVICE_ERROR;
  321. if (!fh->dirs) {
  322. assert(fh->offset == 0);
  323. fh->dirs = fs_opendir(fh->path);
  324. if (!fh->dirs)
  325. return EFI_DEVICE_ERROR;
  326. fh->dent = NULL;
  327. }
  328. /*
  329. * So this is a bit awkward. Since fs layer is stateful and we
  330. * can't rewind an entry, in the EFI_BUFFER_TOO_SMALL case below
  331. * we might have to return without consuming the dent.. so we
  332. * have to stash it for next call.
  333. */
  334. if (fh->dent) {
  335. dent = fh->dent;
  336. } else {
  337. dent = fs_readdir(fh->dirs);
  338. }
  339. if (!dent) {
  340. /* no more files in directory */
  341. *buffer_size = 0;
  342. return EFI_SUCCESS;
  343. }
  344. /* check buffer size: */
  345. required_size = sizeof(*info) +
  346. 2 * (utf8_utf16_strlen(dent->name) + 1);
  347. if (*buffer_size < required_size) {
  348. *buffer_size = required_size;
  349. fh->dent = dent;
  350. return EFI_BUFFER_TOO_SMALL;
  351. }
  352. fh->dent = NULL;
  353. *buffer_size = required_size;
  354. memset(info, 0, required_size);
  355. info->size = required_size;
  356. info->file_size = dent->size;
  357. info->physical_size = dent->size;
  358. if (dent->type == FS_DT_DIR)
  359. info->attribute |= EFI_FILE_DIRECTORY;
  360. dst = info->file_name;
  361. utf8_utf16_strcpy(&dst, dent->name);
  362. fh->offset++;
  363. return EFI_SUCCESS;
  364. }
  365. static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file,
  366. efi_uintn_t *buffer_size, void *buffer)
  367. {
  368. struct file_handle *fh = to_fh(file);
  369. efi_status_t ret = EFI_SUCCESS;
  370. u64 bs;
  371. EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
  372. if (!buffer_size || !buffer) {
  373. ret = EFI_INVALID_PARAMETER;
  374. goto error;
  375. }
  376. bs = *buffer_size;
  377. if (fh->isdir)
  378. ret = dir_read(fh, &bs, buffer);
  379. else
  380. ret = file_read(fh, &bs, buffer);
  381. if (bs <= SIZE_MAX)
  382. *buffer_size = bs;
  383. else
  384. *buffer_size = SIZE_MAX;
  385. error:
  386. return EFI_EXIT(ret);
  387. }
  388. /**
  389. * efi_file_write() - write to file
  390. *
  391. * This function implements the Write() service of the EFI_FILE_PROTOCOL.
  392. *
  393. * See the Unified Extensible Firmware Interface (UEFI) specification for
  394. * details.
  395. *
  396. * @file: file handle
  397. * @buffer_size: number of bytes to write
  398. * @buffer: buffer with the bytes to write
  399. * Return: status code
  400. */
  401. static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
  402. efi_uintn_t *buffer_size,
  403. void *buffer)
  404. {
  405. struct file_handle *fh = to_fh(file);
  406. efi_status_t ret = EFI_SUCCESS;
  407. loff_t actwrite;
  408. EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
  409. if (!file || !buffer_size || !buffer) {
  410. ret = EFI_INVALID_PARAMETER;
  411. goto out;
  412. }
  413. if (fh->isdir) {
  414. ret = EFI_UNSUPPORTED;
  415. goto out;
  416. }
  417. if (!(fh->open_mode & EFI_FILE_MODE_WRITE)) {
  418. ret = EFI_ACCESS_DENIED;
  419. goto out;
  420. }
  421. if (!*buffer_size)
  422. goto out;
  423. if (set_blk_dev(fh)) {
  424. ret = EFI_DEVICE_ERROR;
  425. goto out;
  426. }
  427. if (fs_write(fh->path, map_to_sysmem(buffer), fh->offset, *buffer_size,
  428. &actwrite)) {
  429. ret = EFI_DEVICE_ERROR;
  430. goto out;
  431. }
  432. *buffer_size = actwrite;
  433. fh->offset += actwrite;
  434. out:
  435. return EFI_EXIT(ret);
  436. }
  437. /**
  438. * efi_file_getpos() - get current position in file
  439. *
  440. * This function implements the GetPosition service of the EFI file protocol.
  441. * See the UEFI spec for details.
  442. *
  443. * @file: file handle
  444. * @pos: pointer to file position
  445. * Return: status code
  446. */
  447. static efi_status_t EFIAPI efi_file_getpos(struct efi_file_handle *file,
  448. u64 *pos)
  449. {
  450. efi_status_t ret = EFI_SUCCESS;
  451. struct file_handle *fh = to_fh(file);
  452. EFI_ENTRY("%p, %p", file, pos);
  453. if (fh->isdir) {
  454. ret = EFI_UNSUPPORTED;
  455. goto out;
  456. }
  457. *pos = fh->offset;
  458. out:
  459. return EFI_EXIT(ret);
  460. }
  461. /**
  462. * efi_file_setpos() - set current position in file
  463. *
  464. * This function implements the SetPosition service of the EFI file protocol.
  465. * See the UEFI spec for details.
  466. *
  467. * @file: file handle
  468. * @pos: new file position
  469. * Return: status code
  470. */
  471. static efi_status_t EFIAPI efi_file_setpos(struct efi_file_handle *file,
  472. u64 pos)
  473. {
  474. struct file_handle *fh = to_fh(file);
  475. efi_status_t ret = EFI_SUCCESS;
  476. EFI_ENTRY("%p, %llu", file, pos);
  477. if (fh->isdir) {
  478. if (pos != 0) {
  479. ret = EFI_UNSUPPORTED;
  480. goto error;
  481. }
  482. fs_closedir(fh->dirs);
  483. fh->dirs = NULL;
  484. }
  485. if (pos == ~0ULL) {
  486. loff_t file_size;
  487. ret = efi_get_file_size(fh, &file_size);
  488. if (ret != EFI_SUCCESS)
  489. goto error;
  490. pos = file_size;
  491. }
  492. fh->offset = pos;
  493. error:
  494. return EFI_EXIT(ret);
  495. }
  496. static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file,
  497. const efi_guid_t *info_type,
  498. efi_uintn_t *buffer_size,
  499. void *buffer)
  500. {
  501. struct file_handle *fh = to_fh(file);
  502. efi_status_t ret = EFI_SUCCESS;
  503. u16 *dst;
  504. EFI_ENTRY("%p, %pUl, %p, %p", file, info_type, buffer_size, buffer);
  505. if (!file || !info_type || !buffer_size ||
  506. (*buffer_size && !buffer)) {
  507. ret = EFI_INVALID_PARAMETER;
  508. goto error;
  509. }
  510. if (!guidcmp(info_type, &efi_file_info_guid)) {
  511. struct efi_file_info *info = buffer;
  512. char *filename = basename(fh);
  513. unsigned int required_size;
  514. loff_t file_size;
  515. /* check buffer size: */
  516. required_size = sizeof(*info) +
  517. 2 * (utf8_utf16_strlen(filename) + 1);
  518. if (*buffer_size < required_size) {
  519. *buffer_size = required_size;
  520. ret = EFI_BUFFER_TOO_SMALL;
  521. goto error;
  522. }
  523. ret = efi_get_file_size(fh, &file_size);
  524. if (ret != EFI_SUCCESS)
  525. goto error;
  526. memset(info, 0, required_size);
  527. info->size = required_size;
  528. info->file_size = file_size;
  529. info->physical_size = file_size;
  530. if (fh->isdir)
  531. info->attribute |= EFI_FILE_DIRECTORY;
  532. dst = info->file_name;
  533. utf8_utf16_strcpy(&dst, filename);
  534. } else if (!guidcmp(info_type, &efi_file_system_info_guid)) {
  535. struct efi_file_system_info *info = buffer;
  536. struct disk_partition part;
  537. efi_uintn_t required_size;
  538. int r;
  539. if (fh->fs->part >= 1)
  540. r = part_get_info(fh->fs->desc, fh->fs->part, &part);
  541. else
  542. r = part_get_info_whole_disk(fh->fs->desc, &part);
  543. if (r < 0) {
  544. ret = EFI_DEVICE_ERROR;
  545. goto error;
  546. }
  547. required_size = sizeof(*info) + 2;
  548. if (*buffer_size < required_size) {
  549. *buffer_size = required_size;
  550. ret = EFI_BUFFER_TOO_SMALL;
  551. goto error;
  552. }
  553. memset(info, 0, required_size);
  554. info->size = required_size;
  555. /*
  556. * TODO: We cannot determine if the volume can be written to.
  557. */
  558. info->read_only = false;
  559. info->volume_size = part.size * part.blksz;
  560. /*
  561. * TODO: We currently have no function to determine the free
  562. * space. The volume size is the best upper bound we have.
  563. */
  564. info->free_space = info->volume_size;
  565. info->block_size = part.blksz;
  566. /*
  567. * TODO: The volume label is not available in U-Boot.
  568. */
  569. info->volume_label[0] = 0;
  570. } else if (!guidcmp(info_type, &efi_system_volume_label_id)) {
  571. if (*buffer_size < 2) {
  572. *buffer_size = 2;
  573. ret = EFI_BUFFER_TOO_SMALL;
  574. goto error;
  575. }
  576. *(u16 *)buffer = 0;
  577. } else {
  578. ret = EFI_UNSUPPORTED;
  579. }
  580. error:
  581. return EFI_EXIT(ret);
  582. }
  583. static efi_status_t EFIAPI efi_file_setinfo(struct efi_file_handle *file,
  584. const efi_guid_t *info_type,
  585. efi_uintn_t buffer_size,
  586. void *buffer)
  587. {
  588. struct file_handle *fh = to_fh(file);
  589. efi_status_t ret = EFI_UNSUPPORTED;
  590. EFI_ENTRY("%p, %pUl, %zu, %p", file, info_type, buffer_size, buffer);
  591. if (!guidcmp(info_type, &efi_file_info_guid)) {
  592. struct efi_file_info *info = (struct efi_file_info *)buffer;
  593. char *filename = basename(fh);
  594. char *new_file_name, *pos;
  595. loff_t file_size;
  596. /* The buffer will always contain a file name. */
  597. if (buffer_size < sizeof(struct efi_file_info) + 2 ||
  598. buffer_size < info->size) {
  599. ret = EFI_BAD_BUFFER_SIZE;
  600. goto out;
  601. }
  602. /* We cannot change the directory attribute */
  603. if (!fh->isdir != !(info->attribute & EFI_FILE_DIRECTORY)) {
  604. ret = EFI_ACCESS_DENIED;
  605. goto out;
  606. }
  607. /* Check for renaming */
  608. new_file_name = malloc(utf16_utf8_strlen(info->file_name));
  609. if (!new_file_name) {
  610. ret = EFI_OUT_OF_RESOURCES;
  611. goto out;
  612. }
  613. pos = new_file_name;
  614. utf16_utf8_strcpy(&pos, info->file_name);
  615. if (strcmp(new_file_name, filename)) {
  616. /* TODO: we do not support renaming */
  617. EFI_PRINT("Renaming not supported\n");
  618. free(new_file_name);
  619. ret = EFI_ACCESS_DENIED;
  620. goto out;
  621. }
  622. free(new_file_name);
  623. /* Check for truncation */
  624. ret = efi_get_file_size(fh, &file_size);
  625. if (ret != EFI_SUCCESS)
  626. goto out;
  627. if (file_size != info->file_size) {
  628. /* TODO: we do not support truncation */
  629. EFI_PRINT("Truncation not supported\n");
  630. ret = EFI_ACCESS_DENIED;
  631. goto out;
  632. }
  633. /*
  634. * We do not care for the other attributes
  635. * TODO: Support read only
  636. */
  637. ret = EFI_SUCCESS;
  638. } else {
  639. /* TODO: We do not support changing the volume label */
  640. ret = EFI_UNSUPPORTED;
  641. }
  642. out:
  643. return EFI_EXIT(ret);
  644. }
  645. static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *file)
  646. {
  647. EFI_ENTRY("%p", file);
  648. return EFI_EXIT(EFI_SUCCESS);
  649. }
  650. static efi_status_t EFIAPI efi_file_open_ex(struct efi_file_handle *file,
  651. struct efi_file_handle **new_handle,
  652. u16 *file_name, u64 open_mode, u64 attributes,
  653. struct efi_file_io_token *token)
  654. {
  655. return EFI_UNSUPPORTED;
  656. }
  657. static efi_status_t EFIAPI efi_file_read_ex(struct efi_file_handle *file,
  658. struct efi_file_io_token *token)
  659. {
  660. return EFI_UNSUPPORTED;
  661. }
  662. static efi_status_t EFIAPI efi_file_write_ex(struct efi_file_handle *file,
  663. struct efi_file_io_token *token)
  664. {
  665. return EFI_UNSUPPORTED;
  666. }
  667. static efi_status_t EFIAPI efi_file_flush_ex(struct efi_file_handle *file,
  668. struct efi_file_io_token *token)
  669. {
  670. return EFI_UNSUPPORTED;
  671. }
  672. static const struct efi_file_handle efi_file_handle_protocol = {
  673. .rev = EFI_FILE_PROTOCOL_REVISION2,
  674. .open = efi_file_open,
  675. .close = efi_file_close,
  676. .delete = efi_file_delete,
  677. .read = efi_file_read,
  678. .write = efi_file_write,
  679. .getpos = efi_file_getpos,
  680. .setpos = efi_file_setpos,
  681. .getinfo = efi_file_getinfo,
  682. .setinfo = efi_file_setinfo,
  683. .flush = efi_file_flush,
  684. .open_ex = efi_file_open_ex,
  685. .read_ex = efi_file_read_ex,
  686. .write_ex = efi_file_write_ex,
  687. .flush_ex = efi_file_flush_ex,
  688. };
  689. /**
  690. * efi_file_from_path() - open file via device path
  691. *
  692. * @fp: device path
  693. * @return: EFI_FILE_PROTOCOL for the file or NULL
  694. */
  695. struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp)
  696. {
  697. struct efi_simple_file_system_protocol *v;
  698. struct efi_file_handle *f;
  699. efi_status_t ret;
  700. v = efi_fs_from_path(fp);
  701. if (!v)
  702. return NULL;
  703. EFI_CALL(ret = v->open_volume(v, &f));
  704. if (ret != EFI_SUCCESS)
  705. return NULL;
  706. /* Skip over device-path nodes before the file path. */
  707. while (fp && !EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH))
  708. fp = efi_dp_next(fp);
  709. /*
  710. * Step through the nodes of the directory path until the actual file
  711. * node is reached which is the final node in the device path.
  712. */
  713. while (fp) {
  714. struct efi_device_path_file_path *fdp =
  715. container_of(fp, struct efi_device_path_file_path, dp);
  716. struct efi_file_handle *f2;
  717. u16 *filename;
  718. if (!EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH)) {
  719. printf("bad file path!\n");
  720. f->close(f);
  721. return NULL;
  722. }
  723. filename = u16_strdup(fdp->str);
  724. if (!filename)
  725. return NULL;
  726. EFI_CALL(ret = f->open(f, &f2, filename,
  727. EFI_FILE_MODE_READ, 0));
  728. free(filename);
  729. if (ret != EFI_SUCCESS)
  730. return NULL;
  731. fp = efi_dp_next(fp);
  732. EFI_CALL(f->close(f));
  733. f = f2;
  734. }
  735. return f;
  736. }
  737. static efi_status_t EFIAPI
  738. efi_open_volume(struct efi_simple_file_system_protocol *this,
  739. struct efi_file_handle **root)
  740. {
  741. struct file_system *fs = to_fs(this);
  742. EFI_ENTRY("%p, %p", this, root);
  743. *root = file_open(fs, NULL, NULL, 0, 0);
  744. return EFI_EXIT(EFI_SUCCESS);
  745. }
  746. struct efi_simple_file_system_protocol *
  747. efi_simple_file_system(struct blk_desc *desc, int part,
  748. struct efi_device_path *dp)
  749. {
  750. struct file_system *fs;
  751. fs = calloc(1, sizeof(*fs));
  752. fs->base.rev = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
  753. fs->base.open_volume = efi_open_volume;
  754. fs->desc = desc;
  755. fs->part = part;
  756. fs->dp = dp;
  757. return &fs->base;
  758. }