ofdisk.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. /* ofdisk.c - Open Firmware disk access. */
  2. /*
  3. * GRUB -- GRand Unified Bootloader
  4. * Copyright (C) 2004,2006,2007,2008,2009 Free Software Foundation, Inc.
  5. *
  6. * GRUB is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * GRUB is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <grub/misc.h>
  20. #include <grub/disk.h>
  21. #include <grub/mm.h>
  22. #include <grub/ieee1275/ieee1275.h>
  23. #include <grub/ieee1275/ofdisk.h>
  24. #include <grub/i18n.h>
  25. #include <grub/time.h>
  26. static char *last_devpath;
  27. static grub_ieee1275_ihandle_t last_ihandle;
  28. struct ofdisk_hash_ent
  29. {
  30. char *devpath;
  31. char *open_path;
  32. char *grub_devpath;
  33. int is_boot;
  34. int is_removable;
  35. int block_size_fails;
  36. /* Pointer to shortest available name on nodes representing canonical names,
  37. otherwise NULL. */
  38. const char *shortest;
  39. const char *grub_shortest;
  40. struct ofdisk_hash_ent *next;
  41. };
  42. static grub_err_t
  43. grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size,
  44. struct ofdisk_hash_ent *op);
  45. #define OFDISK_HASH_SZ 8
  46. static struct ofdisk_hash_ent *ofdisk_hash[OFDISK_HASH_SZ];
  47. static int
  48. ofdisk_hash_fn (const char *devpath)
  49. {
  50. int hash = 0;
  51. while (*devpath)
  52. hash ^= *devpath++;
  53. return (hash & (OFDISK_HASH_SZ - 1));
  54. }
  55. static struct ofdisk_hash_ent *
  56. ofdisk_hash_find (const char *devpath)
  57. {
  58. struct ofdisk_hash_ent *p = ofdisk_hash[ofdisk_hash_fn(devpath)];
  59. while (p)
  60. {
  61. if (!grub_strcmp (p->devpath, devpath))
  62. break;
  63. p = p->next;
  64. }
  65. return p;
  66. }
  67. static struct ofdisk_hash_ent *
  68. ofdisk_hash_add_real (char *devpath)
  69. {
  70. struct ofdisk_hash_ent *p;
  71. struct ofdisk_hash_ent **head = &ofdisk_hash[ofdisk_hash_fn(devpath)];
  72. const char *iptr;
  73. char *optr;
  74. p = grub_zalloc (sizeof (*p));
  75. if (!p)
  76. return NULL;
  77. p->devpath = devpath;
  78. p->grub_devpath = grub_malloc (sizeof ("ieee1275/")
  79. + 2 * grub_strlen (p->devpath));
  80. if (!p->grub_devpath)
  81. {
  82. grub_free (p);
  83. return NULL;
  84. }
  85. if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0))
  86. {
  87. p->open_path = grub_malloc (grub_strlen (p->devpath) + 3);
  88. if (!p->open_path)
  89. {
  90. grub_free (p->grub_devpath);
  91. grub_free (p);
  92. return NULL;
  93. }
  94. optr = grub_stpcpy (p->open_path, p->devpath);
  95. *optr++ = ':';
  96. *optr++ = '0';
  97. *optr = '\0';
  98. }
  99. else
  100. p->open_path = p->devpath;
  101. optr = grub_stpcpy (p->grub_devpath, "ieee1275/");
  102. for (iptr = p->devpath; *iptr; )
  103. {
  104. if (*iptr == ',')
  105. *optr++ = '\\';
  106. *optr++ = *iptr++;
  107. }
  108. *optr = 0;
  109. p->next = *head;
  110. *head = p;
  111. return p;
  112. }
  113. static int
  114. check_string_removable (const char *str)
  115. {
  116. const char *ptr = grub_strrchr (str, '/');
  117. if (ptr)
  118. ptr++;
  119. else
  120. ptr = str;
  121. return (grub_strncmp (ptr, "cdrom", 5) == 0 || grub_strncmp (ptr, "fd", 2) == 0);
  122. }
  123. static struct ofdisk_hash_ent *
  124. ofdisk_hash_add (char *devpath, char *curcan)
  125. {
  126. struct ofdisk_hash_ent *p, *pcan;
  127. p = ofdisk_hash_add_real (devpath);
  128. grub_dprintf ("disk", "devpath = %s, canonical = %s\n", devpath, curcan);
  129. if (!curcan)
  130. {
  131. p->shortest = p->devpath;
  132. p->grub_shortest = p->grub_devpath;
  133. if (check_string_removable (devpath))
  134. p->is_removable = 1;
  135. return p;
  136. }
  137. pcan = ofdisk_hash_find (curcan);
  138. if (!pcan)
  139. pcan = ofdisk_hash_add_real (curcan);
  140. else
  141. grub_free (curcan);
  142. if (check_string_removable (devpath) || check_string_removable (curcan))
  143. pcan->is_removable = 1;
  144. if (!pcan)
  145. grub_errno = GRUB_ERR_NONE;
  146. else
  147. {
  148. if (!pcan->shortest
  149. || grub_strlen (pcan->shortest) > grub_strlen (devpath))
  150. {
  151. pcan->shortest = p->devpath;
  152. pcan->grub_shortest = p->grub_devpath;
  153. }
  154. }
  155. return p;
  156. }
  157. static void
  158. dev_iterate_real (const char *name, const char *path)
  159. {
  160. struct ofdisk_hash_ent *op;
  161. grub_dprintf ("disk", "disk name = %s, path = %s\n", name,
  162. path);
  163. op = ofdisk_hash_find (path);
  164. if (!op)
  165. {
  166. char *name_dup = grub_strdup (name);
  167. char *can = grub_strdup (path);
  168. if (!name_dup || !can)
  169. {
  170. grub_errno = GRUB_ERR_NONE;
  171. grub_free (name_dup);
  172. grub_free (can);
  173. return;
  174. }
  175. op = ofdisk_hash_add (name_dup, can);
  176. }
  177. return;
  178. }
  179. static void
  180. dev_iterate (const struct grub_ieee1275_devalias *alias)
  181. {
  182. if (grub_strcmp (alias->type, "vscsi") == 0)
  183. {
  184. static grub_ieee1275_ihandle_t ihandle;
  185. struct set_color_args
  186. {
  187. struct grub_ieee1275_common_hdr common;
  188. grub_ieee1275_cell_t method;
  189. grub_ieee1275_cell_t ihandle;
  190. grub_ieee1275_cell_t catch_result;
  191. grub_ieee1275_cell_t nentries;
  192. grub_ieee1275_cell_t table;
  193. }
  194. args;
  195. char *buf, *bufptr;
  196. unsigned i;
  197. if (grub_ieee1275_open (alias->path, &ihandle))
  198. return;
  199. /* This method doesn't need memory allocation for the table. Open
  200. firmware takes care of all memory management and the result table
  201. stays in memory and is never freed. */
  202. INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3);
  203. args.method = (grub_ieee1275_cell_t) "vscsi-report-luns";
  204. args.ihandle = ihandle;
  205. args.table = 0;
  206. args.nentries = 0;
  207. if (IEEE1275_CALL_ENTRY_FN (&args) == -1 || args.catch_result)
  208. {
  209. grub_ieee1275_close (ihandle);
  210. return;
  211. }
  212. buf = grub_malloc (grub_strlen (alias->path) + 32);
  213. if (!buf)
  214. return;
  215. bufptr = grub_stpcpy (buf, alias->path);
  216. for (i = 0; i < args.nentries; i++)
  217. {
  218. grub_uint64_t *ptr;
  219. ptr = *(grub_uint64_t **) (args.table + 4 + 8 * i);
  220. while (*ptr)
  221. {
  222. grub_snprintf (bufptr, 32, "/disk@%" PRIxGRUB_UINT64_T, *ptr++);
  223. dev_iterate_real (buf, buf);
  224. }
  225. }
  226. grub_ieee1275_close (ihandle);
  227. grub_free (buf);
  228. return;
  229. }
  230. else if (grub_strcmp (alias->type, "sas_ioa") == 0)
  231. {
  232. /* The method returns the number of disks and a table where
  233. * each ID is 64-bit long. Example of sas paths:
  234. * /pci@80000002000001f/pci1014,034A@0/sas/disk@c05db70800
  235. * /pci@80000002000001f/pci1014,034A@0/sas/disk@a05db70800
  236. * /pci@80000002000001f/pci1014,034A@0/sas/disk@805db70800 */
  237. struct sas_children
  238. {
  239. struct grub_ieee1275_common_hdr common;
  240. grub_ieee1275_cell_t method;
  241. grub_ieee1275_cell_t ihandle;
  242. grub_ieee1275_cell_t max;
  243. grub_ieee1275_cell_t table;
  244. grub_ieee1275_cell_t catch_result;
  245. grub_ieee1275_cell_t nentries;
  246. }
  247. args;
  248. char *buf, *bufptr;
  249. unsigned i;
  250. grub_uint64_t *table;
  251. grub_uint16_t table_size;
  252. grub_ieee1275_ihandle_t ihandle;
  253. buf = grub_malloc (grub_strlen (alias->path) +
  254. sizeof ("/disk@7766554433221100"));
  255. if (!buf)
  256. return;
  257. bufptr = grub_stpcpy (buf, alias->path);
  258. /* Power machines documentation specify 672 as maximum SAS disks in
  259. one system. Using a slightly larger value to be safe. */
  260. table_size = 768;
  261. table = grub_malloc (table_size * sizeof (grub_uint64_t));
  262. if (!table)
  263. {
  264. grub_free (buf);
  265. return;
  266. }
  267. if (grub_ieee1275_open (alias->path, &ihandle))
  268. {
  269. grub_free (buf);
  270. grub_free (table);
  271. return;
  272. }
  273. INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 2);
  274. args.method = (grub_ieee1275_cell_t) "get-sas-children";
  275. args.ihandle = ihandle;
  276. args.max = table_size;
  277. args.table = (grub_ieee1275_cell_t) table;
  278. args.catch_result = 0;
  279. args.nentries = 0;
  280. if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
  281. {
  282. grub_ieee1275_close (ihandle);
  283. grub_free (table);
  284. grub_free (buf);
  285. return;
  286. }
  287. for (i = 0; i < args.nentries; i++)
  288. {
  289. grub_snprintf (bufptr, sizeof ("/disk@7766554433221100"),
  290. "/disk@%" PRIxGRUB_UINT64_T, table[i]);
  291. dev_iterate_real (buf, buf);
  292. }
  293. grub_ieee1275_close (ihandle);
  294. grub_free (table);
  295. grub_free (buf);
  296. }
  297. if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS)
  298. && grub_strcmp (alias->type, "block") == 0)
  299. {
  300. dev_iterate_real (alias->path, alias->path);
  301. return;
  302. }
  303. {
  304. struct grub_ieee1275_devalias child;
  305. FOR_IEEE1275_DEVCHILDREN(alias->path, child)
  306. dev_iterate (&child);
  307. }
  308. }
  309. static void
  310. scan (void)
  311. {
  312. struct grub_ieee1275_devalias alias;
  313. FOR_IEEE1275_DEVALIASES(alias)
  314. {
  315. if (grub_strcmp (alias.type, "block") != 0)
  316. continue;
  317. dev_iterate_real (alias.name, alias.path);
  318. }
  319. FOR_IEEE1275_DEVCHILDREN("/", alias)
  320. dev_iterate (&alias);
  321. }
  322. static int
  323. grub_ofdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
  324. grub_disk_pull_t pull)
  325. {
  326. unsigned i;
  327. if (pull != GRUB_DISK_PULL_NONE)
  328. return 0;
  329. scan ();
  330. for (i = 0; i < ARRAY_SIZE (ofdisk_hash); i++)
  331. {
  332. static struct ofdisk_hash_ent *ent;
  333. for (ent = ofdisk_hash[i]; ent; ent = ent->next)
  334. {
  335. if (!ent->shortest)
  336. continue;
  337. if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY))
  338. {
  339. grub_ieee1275_phandle_t dev;
  340. char tmp[8];
  341. if (grub_ieee1275_finddevice (ent->devpath, &dev))
  342. {
  343. grub_dprintf ("disk", "finddevice (%s) failed\n",
  344. ent->devpath);
  345. continue;
  346. }
  347. if (grub_ieee1275_get_property (dev, "iconname", tmp,
  348. sizeof tmp, 0))
  349. {
  350. grub_dprintf ("disk", "get iconname failed\n");
  351. continue;
  352. }
  353. if (grub_strcmp (tmp, "sdmmc") != 0)
  354. {
  355. grub_dprintf ("disk", "device is not an SD card\n");
  356. continue;
  357. }
  358. }
  359. if (!ent->is_boot && ent->is_removable)
  360. continue;
  361. if (hook (ent->grub_shortest, hook_data))
  362. return 1;
  363. }
  364. }
  365. return 0;
  366. }
  367. static char *
  368. compute_dev_path (const char *name)
  369. {
  370. char *devpath = grub_malloc (grub_strlen (name) + 3);
  371. char *p, c;
  372. if (!devpath)
  373. return NULL;
  374. /* Un-escape commas. */
  375. p = devpath;
  376. while ((c = *name++) != '\0')
  377. {
  378. if (c == '\\' && *name == ',')
  379. {
  380. *p++ = ',';
  381. name++;
  382. }
  383. else
  384. *p++ = c;
  385. }
  386. *p++ = '\0';
  387. return devpath;
  388. }
  389. static grub_err_t
  390. grub_ofdisk_open (const char *name, grub_disk_t disk)
  391. {
  392. grub_ieee1275_phandle_t dev;
  393. char *devpath;
  394. /* XXX: This should be large enough for any possible case. */
  395. char prop[64];
  396. grub_ssize_t actual;
  397. grub_uint32_t block_size = 0;
  398. grub_err_t err;
  399. if (grub_strncmp (name, "ieee1275/", sizeof ("ieee1275/") - 1) != 0)
  400. return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
  401. "not IEEE1275 device");
  402. devpath = compute_dev_path (name + sizeof ("ieee1275/") - 1);
  403. if (! devpath)
  404. return grub_errno;
  405. grub_dprintf ("disk", "Opening `%s'.\n", devpath);
  406. if (grub_ieee1275_finddevice (devpath, &dev))
  407. {
  408. grub_free (devpath);
  409. return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
  410. "can't read device properties");
  411. }
  412. if (grub_ieee1275_get_property (dev, "device_type", prop, sizeof (prop),
  413. &actual))
  414. {
  415. grub_free (devpath);
  416. return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type");
  417. }
  418. if (grub_strcmp (prop, "block"))
  419. {
  420. grub_free (devpath);
  421. return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a block device");
  422. }
  423. /* XXX: There is no property to read the number of blocks. There
  424. should be a property `#blocks', but it is not there. Perhaps it
  425. is possible to use seek for this. */
  426. disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
  427. {
  428. struct ofdisk_hash_ent *op;
  429. op = ofdisk_hash_find (devpath);
  430. if (!op)
  431. op = ofdisk_hash_add (devpath, NULL);
  432. if (!op)
  433. {
  434. grub_free (devpath);
  435. return grub_errno;
  436. }
  437. disk->id = (unsigned long) op;
  438. disk->data = op->open_path;
  439. err = grub_ofdisk_get_block_size (devpath, &block_size, op);
  440. if (err)
  441. {
  442. grub_free (devpath);
  443. return err;
  444. }
  445. if (block_size != 0)
  446. {
  447. for (disk->log_sector_size = 0;
  448. (1U << disk->log_sector_size) < block_size;
  449. disk->log_sector_size++);
  450. }
  451. else
  452. disk->log_sector_size = 9;
  453. }
  454. grub_free (devpath);
  455. return 0;
  456. }
  457. static void
  458. grub_ofdisk_close (grub_disk_t disk)
  459. {
  460. if (disk->data == last_devpath)
  461. {
  462. if (last_ihandle)
  463. grub_ieee1275_close (last_ihandle);
  464. last_ihandle = 0;
  465. last_devpath = NULL;
  466. }
  467. disk->data = 0;
  468. }
  469. static grub_err_t
  470. grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector)
  471. {
  472. grub_ssize_t status;
  473. unsigned long long pos;
  474. if (disk->data != last_devpath)
  475. {
  476. if (last_ihandle)
  477. grub_ieee1275_close (last_ihandle);
  478. last_ihandle = 0;
  479. last_devpath = NULL;
  480. grub_ieee1275_open (disk->data, &last_ihandle);
  481. if (! last_ihandle)
  482. return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
  483. last_devpath = disk->data;
  484. }
  485. pos = sector << disk->log_sector_size;
  486. grub_ieee1275_seek (last_ihandle, pos, &status);
  487. if (status < 0)
  488. return grub_error (GRUB_ERR_READ_ERROR,
  489. "seek error, can't seek block %llu",
  490. (long long) sector);
  491. return 0;
  492. }
  493. static grub_err_t
  494. grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
  495. grub_size_t size, char *buf)
  496. {
  497. grub_err_t err;
  498. grub_ssize_t actual;
  499. err = grub_ofdisk_prepare (disk, sector);
  500. if (err)
  501. return err;
  502. grub_ieee1275_read (last_ihandle, buf, size << disk->log_sector_size,
  503. &actual);
  504. if (actual != (grub_ssize_t) (size << disk->log_sector_size))
  505. return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx "
  506. "from `%s'"),
  507. (unsigned long long) sector,
  508. disk->name);
  509. return 0;
  510. }
  511. static grub_err_t
  512. grub_ofdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
  513. grub_size_t size, const char *buf)
  514. {
  515. grub_err_t err;
  516. grub_ssize_t actual;
  517. err = grub_ofdisk_prepare (disk, sector);
  518. if (err)
  519. return err;
  520. grub_ieee1275_write (last_ihandle, buf, size << disk->log_sector_size,
  521. &actual);
  522. if (actual != (grub_ssize_t) (size << disk->log_sector_size))
  523. return grub_error (GRUB_ERR_WRITE_ERROR, N_("failure writing sector 0x%llx "
  524. "to `%s'"),
  525. (unsigned long long) sector,
  526. disk->name);
  527. return 0;
  528. }
  529. static struct grub_disk_dev grub_ofdisk_dev =
  530. {
  531. .name = "ofdisk",
  532. .id = GRUB_DISK_DEVICE_OFDISK_ID,
  533. .iterate = grub_ofdisk_iterate,
  534. .open = grub_ofdisk_open,
  535. .close = grub_ofdisk_close,
  536. .read = grub_ofdisk_read,
  537. .write = grub_ofdisk_write,
  538. .next = 0
  539. };
  540. static void
  541. insert_bootpath (void)
  542. {
  543. char *bootpath;
  544. grub_ssize_t bootpath_size;
  545. char *type;
  546. if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, "bootpath",
  547. &bootpath_size)
  548. || bootpath_size <= 0)
  549. {
  550. /* Should never happen. */
  551. grub_printf ("/chosen/bootpath property missing!\n");
  552. return;
  553. }
  554. bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64);
  555. if (! bootpath)
  556. {
  557. grub_print_error ();
  558. return;
  559. }
  560. grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", bootpath,
  561. (grub_size_t) bootpath_size + 1, 0);
  562. bootpath[bootpath_size] = '\0';
  563. /* Transform an OF device path to a GRUB path. */
  564. type = grub_ieee1275_get_device_type (bootpath);
  565. if (!(type && grub_strcmp (type, "network") == 0))
  566. {
  567. struct ofdisk_hash_ent *op;
  568. char *device = grub_ieee1275_get_devname (bootpath);
  569. op = ofdisk_hash_add (device, NULL);
  570. op->is_boot = 1;
  571. }
  572. grub_free (type);
  573. grub_free (bootpath);
  574. }
  575. void
  576. grub_ofdisk_fini (void)
  577. {
  578. if (last_ihandle)
  579. grub_ieee1275_close (last_ihandle);
  580. last_ihandle = 0;
  581. last_devpath = NULL;
  582. grub_disk_dev_unregister (&grub_ofdisk_dev);
  583. }
  584. void
  585. grub_ofdisk_init (void)
  586. {
  587. grub_disk_firmware_fini = grub_ofdisk_fini;
  588. insert_bootpath ();
  589. grub_disk_dev_register (&grub_ofdisk_dev);
  590. }
  591. static grub_err_t
  592. grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size,
  593. struct ofdisk_hash_ent *op)
  594. {
  595. struct size_args_ieee1275
  596. {
  597. struct grub_ieee1275_common_hdr common;
  598. grub_ieee1275_cell_t method;
  599. grub_ieee1275_cell_t ihandle;
  600. grub_ieee1275_cell_t result;
  601. grub_ieee1275_cell_t size1;
  602. grub_ieee1275_cell_t size2;
  603. } args_ieee1275;
  604. if (last_ihandle)
  605. grub_ieee1275_close (last_ihandle);
  606. last_ihandle = 0;
  607. last_devpath = NULL;
  608. grub_ieee1275_open (device, &last_ihandle);
  609. if (! last_ihandle)
  610. return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
  611. *block_size = 0;
  612. if (op->block_size_fails >= 2)
  613. return GRUB_ERR_NONE;
  614. INIT_IEEE1275_COMMON (&args_ieee1275.common, "call-method", 2, 2);
  615. args_ieee1275.method = (grub_ieee1275_cell_t) "block-size";
  616. args_ieee1275.ihandle = last_ihandle;
  617. args_ieee1275.result = 1;
  618. if (IEEE1275_CALL_ENTRY_FN (&args_ieee1275) == -1)
  619. {
  620. grub_dprintf ("disk", "can't get block size: failed call-method\n");
  621. op->block_size_fails++;
  622. }
  623. else if (args_ieee1275.result)
  624. {
  625. grub_dprintf ("disk", "can't get block size: %lld\n",
  626. (long long) args_ieee1275.result);
  627. op->block_size_fails++;
  628. }
  629. else if (args_ieee1275.size1
  630. && !(args_ieee1275.size1 & (args_ieee1275.size1 - 1))
  631. && args_ieee1275.size1 >= 512 && args_ieee1275.size1 <= 16384)
  632. {
  633. op->block_size_fails = 0;
  634. *block_size = args_ieee1275.size1;
  635. }
  636. return 0;
  637. }