ieee1275: block-size deblocker support method
[grub.git] / grub-core / kern / ieee1275 / ieee1275.c
1 /* of.c - Access the Open Firmware client interface.  */
2 /*
3  *  GRUB  --  GRand Unified Bootloader
4  *  Copyright (C) 2003,2004,2005,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
20 #include <grub/ieee1275/ieee1275.h>
21 #include <grub/types.h>
22 #include <grub/misc.h>
23
24 #define IEEE1275_PHANDLE_INVALID  ((grub_ieee1275_cell_t) -1)
25 #define IEEE1275_IHANDLE_INVALID  ((grub_ieee1275_cell_t) 0)
26 #define IEEE1275_CELL_INVALID     ((grub_ieee1275_cell_t) -1)
27
28 \f
29
30 int
31 grub_ieee1275_finddevice (const char *name, grub_ieee1275_phandle_t *phandlep)
32 {
33   struct find_device_args
34   {
35     struct grub_ieee1275_common_hdr common;
36     grub_ieee1275_cell_t device;
37     grub_ieee1275_cell_t phandle;
38   }
39   args;
40
41   INIT_IEEE1275_COMMON (&args.common, "finddevice", 1, 1);
42   args.device = (grub_ieee1275_cell_t) name;
43
44   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
45     return -1;
46   *phandlep = args.phandle;
47   if (args.phandle == IEEE1275_PHANDLE_INVALID)
48     return -1;
49   return 0;
50 }
51
52 int
53 grub_ieee1275_get_property (grub_ieee1275_phandle_t phandle,
54                             const char *property, void *buf,
55                             grub_size_t size, grub_ssize_t *actual)
56 {
57   struct get_property_args
58   {
59     struct grub_ieee1275_common_hdr common;
60     grub_ieee1275_cell_t phandle;
61     grub_ieee1275_cell_t prop;
62     grub_ieee1275_cell_t buf;
63     grub_ieee1275_cell_t buflen;
64     grub_ieee1275_cell_t size;
65   }
66   args;
67
68   INIT_IEEE1275_COMMON (&args.common, "getprop", 4, 1);
69   args.phandle = phandle;
70   args.prop = (grub_ieee1275_cell_t) property;
71   args.buf = (grub_ieee1275_cell_t) buf;
72   args.buflen = (grub_ieee1275_cell_t) size;
73
74   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
75     return -1;
76   if (actual)
77     *actual = (grub_ssize_t) args.size;
78   if (args.size == IEEE1275_CELL_INVALID)
79     return -1;
80   return 0;
81 }
82
83 int
84 grub_ieee1275_get_integer_property (grub_ieee1275_phandle_t phandle,
85                                     const char *property, grub_uint32_t *buf,
86                                     grub_size_t size, grub_ssize_t *actual)
87 {
88   int ret;
89   ret = grub_ieee1275_get_property (phandle, property, (void *) buf, size, actual);
90 #ifndef GRUB_CPU_WORDS_BIGENDIAN
91   /* Integer properties are always in big endian.  */
92   if (ret == 0)
93     {
94       unsigned int i;
95       size /= sizeof (grub_uint32_t);
96       for (i = 0; i < size; i++)
97         buf[i] = grub_be_to_cpu32 (buf[i]);
98     }
99 #endif
100   return ret;
101 }
102
103 int
104 grub_ieee1275_next_property (grub_ieee1275_phandle_t phandle, char *prev_prop,
105                              char *prop)
106 {
107   struct get_property_args
108   {
109     struct grub_ieee1275_common_hdr common;
110     grub_ieee1275_cell_t phandle;
111     grub_ieee1275_cell_t prev_prop;
112     grub_ieee1275_cell_t next_prop;
113     grub_ieee1275_cell_t flags;
114   }
115   args;
116
117   INIT_IEEE1275_COMMON (&args.common, "nextprop", 3, 1);
118   args.phandle = phandle;
119   args.prev_prop = (grub_ieee1275_cell_t) prev_prop;
120   args.next_prop = (grub_ieee1275_cell_t) prop;
121   args.flags = (grub_ieee1275_cell_t) -1;
122
123   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
124     return -1;
125   return (int) args.flags;
126 }
127
128 int
129 grub_ieee1275_get_property_length (grub_ieee1275_phandle_t phandle,
130                                    const char *prop, grub_ssize_t *length)
131 {
132   struct get_property_args
133   {
134     struct grub_ieee1275_common_hdr common;
135     grub_ieee1275_cell_t phandle;
136     grub_ieee1275_cell_t prop;
137     grub_ieee1275_cell_t length;
138   }
139   args;
140
141   INIT_IEEE1275_COMMON (&args.common, "getproplen", 2, 1);
142   args.phandle = phandle;
143   args.prop = (grub_ieee1275_cell_t) prop;
144   args.length = (grub_ieee1275_cell_t) -1;
145
146   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
147     return -1;
148   *length = args.length;
149   if (args.length == IEEE1275_CELL_INVALID)
150     return -1;
151   return 0;
152 }
153
154 int
155 grub_ieee1275_instance_to_package (grub_ieee1275_ihandle_t ihandle,
156                                    grub_ieee1275_phandle_t *phandlep)
157 {
158   struct instance_to_package_args
159   {
160     struct grub_ieee1275_common_hdr common;
161     grub_ieee1275_cell_t ihandle;
162     grub_ieee1275_cell_t phandle;
163   }
164   args;
165
166   INIT_IEEE1275_COMMON (&args.common, "instance-to-package", 1, 1);
167   args.ihandle = ihandle;
168
169   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
170     return -1;
171   *phandlep = args.phandle;
172   if (args.phandle == IEEE1275_PHANDLE_INVALID)
173     return -1;
174   return 0;
175 }
176
177 int
178 grub_ieee1275_package_to_path (grub_ieee1275_phandle_t phandle,
179                                char *path, grub_size_t len,
180                                grub_ssize_t *actual)
181 {
182   struct instance_to_package_args
183   {
184     struct grub_ieee1275_common_hdr common;
185     grub_ieee1275_cell_t phandle;
186     grub_ieee1275_cell_t buf;
187     grub_ieee1275_cell_t buflen;
188     grub_ieee1275_cell_t actual;
189   }
190   args;
191
192   INIT_IEEE1275_COMMON (&args.common, "package-to-path", 3, 1);
193   args.phandle = phandle;
194   args.buf = (grub_ieee1275_cell_t) path;
195   args.buflen = (grub_ieee1275_cell_t) len;
196
197   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
198     return -1;
199   if (actual)
200     *actual = args.actual;
201   if (args.actual == IEEE1275_CELL_INVALID)
202     return -1;
203   return 0;
204 }
205
206 int
207 grub_ieee1275_instance_to_path (grub_ieee1275_ihandle_t ihandle,
208                                 char *path, grub_size_t len,
209                                 grub_ssize_t *actual)
210 {
211   struct instance_to_path_args
212   {
213     struct grub_ieee1275_common_hdr common;
214     grub_ieee1275_cell_t ihandle;
215     grub_ieee1275_cell_t buf;
216     grub_ieee1275_cell_t buflen;
217     grub_ieee1275_cell_t actual;
218   }
219   args;
220
221   INIT_IEEE1275_COMMON (&args.common, "instance-to-path", 3, 1);
222   args.ihandle = ihandle;
223   args.buf = (grub_ieee1275_cell_t) path;
224   args.buflen = (grub_ieee1275_cell_t) len;
225
226   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
227     return -1;
228   if (actual)
229     *actual = args.actual;
230   if (args.actual == IEEE1275_CELL_INVALID)
231     return -1;
232   return 0;
233 }
234
235 int
236 grub_ieee1275_write (grub_ieee1275_ihandle_t ihandle, const void *buffer,
237                      grub_size_t len, grub_ssize_t *actualp)
238 {
239   struct write_args
240   {
241     struct grub_ieee1275_common_hdr common;
242     grub_ieee1275_cell_t ihandle;
243     grub_ieee1275_cell_t buf;
244     grub_ieee1275_cell_t len;
245     grub_ieee1275_cell_t actual;
246   }
247   args;
248
249   INIT_IEEE1275_COMMON (&args.common, "write", 3, 1);
250   args.ihandle = ihandle;
251   args.buf = (grub_ieee1275_cell_t) buffer;
252   args.len = (grub_ieee1275_cell_t) len;
253
254   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
255     return -1;
256   if (actualp)
257     *actualp = args.actual;
258   return 0;
259 }
260
261 int
262 grub_ieee1275_read (grub_ieee1275_ihandle_t ihandle, void *buffer,
263                     grub_size_t len, grub_ssize_t *actualp)
264 {
265   struct write_args
266   {
267     struct grub_ieee1275_common_hdr common;
268     grub_ieee1275_cell_t ihandle;
269     grub_ieee1275_cell_t buf;
270     grub_ieee1275_cell_t len;
271     grub_ieee1275_cell_t actual;
272   }
273   args;
274
275   INIT_IEEE1275_COMMON (&args.common, "read", 3, 1);
276   args.ihandle = ihandle;
277   args.buf = (grub_ieee1275_cell_t) buffer;
278   args.len = (grub_ieee1275_cell_t) len;
279
280   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
281     return -1;
282   if (actualp)
283     *actualp = args.actual;
284   return 0;
285 }
286
287 int
288 grub_ieee1275_seek (grub_ieee1275_ihandle_t ihandle, grub_disk_addr_t pos,
289                     grub_ssize_t *result)
290 {
291   struct write_args
292   {
293     struct grub_ieee1275_common_hdr common;
294     grub_ieee1275_cell_t ihandle;
295     grub_ieee1275_cell_t pos_hi;
296     grub_ieee1275_cell_t pos_lo;
297     grub_ieee1275_cell_t result;
298   }
299   args;
300
301   INIT_IEEE1275_COMMON (&args.common, "seek", 3, 1);
302   args.ihandle = ihandle;
303   /* To prevent stupid gcc warning.  */
304 #if GRUB_IEEE1275_CELL_SIZEOF >= 8
305   args.pos_hi = 0;
306   args.pos_lo = pos;
307 #else
308   args.pos_hi = (grub_ieee1275_cell_t) (pos >> (8 * GRUB_IEEE1275_CELL_SIZEOF));
309   args.pos_lo = (grub_ieee1275_cell_t) 
310     (pos & ((1ULL << (8 * GRUB_IEEE1275_CELL_SIZEOF)) - 1));
311 #endif
312
313   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
314     return -1;
315
316   if (result)
317     *result = args.result;
318   return 0;
319 }
320
321 int
322 grub_ieee1275_peer (grub_ieee1275_phandle_t node,
323                     grub_ieee1275_phandle_t *result)
324 {
325   struct peer_args
326   {
327     struct grub_ieee1275_common_hdr common;
328     grub_ieee1275_cell_t node;
329     grub_ieee1275_cell_t result;
330   }
331   args;
332
333   INIT_IEEE1275_COMMON (&args.common, "peer", 1, 1);
334   args.node = node;
335
336   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
337     return -1;
338   *result = args.result;
339   if (args.result == 0)
340     return -1;
341   return 0;
342 }
343
344 int
345 grub_ieee1275_child (grub_ieee1275_phandle_t node,
346                      grub_ieee1275_phandle_t *result)
347 {
348   struct child_args
349   {
350     struct grub_ieee1275_common_hdr common;
351     grub_ieee1275_cell_t node;
352     grub_ieee1275_cell_t result;
353   }
354   args;
355
356   INIT_IEEE1275_COMMON (&args.common, "child", 1, 1);
357   args.node = node;
358   args.result = IEEE1275_PHANDLE_INVALID;
359
360   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
361     return -1;
362   *result = args.result;
363   if (args.result == 0)
364     return -1;
365   return 0;
366 }
367
368 int
369 grub_ieee1275_parent (grub_ieee1275_phandle_t node,
370                       grub_ieee1275_phandle_t *result)
371 {
372   struct parent_args
373   {
374     struct grub_ieee1275_common_hdr common;
375     grub_ieee1275_cell_t node;
376     grub_ieee1275_cell_t result;
377   }
378   args;
379
380   INIT_IEEE1275_COMMON (&args.common, "parent", 1, 1);
381   args.node = node;
382   args.result = IEEE1275_PHANDLE_INVALID;
383
384   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
385     return -1;
386   *result = args.result;
387   return 0;
388 }
389
390 int
391 grub_ieee1275_interpret (const char *command, grub_ieee1275_cell_t *catch)
392 {
393   struct enter_args
394   {
395     struct grub_ieee1275_common_hdr common;
396     grub_ieee1275_cell_t command;
397     grub_ieee1275_cell_t catch;
398   }
399   args;
400
401   if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET))
402     return -1;
403
404   INIT_IEEE1275_COMMON (&args.common, "interpret", 1, 1);
405   args.command = (grub_ieee1275_cell_t) command;
406
407   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
408     return -1;
409   if (catch)
410     *catch = args.catch;
411   return 0;
412 }
413
414 int
415 grub_ieee1275_enter (void)
416 {
417   struct enter_args
418   {
419     struct grub_ieee1275_common_hdr common;
420   }
421   args;
422
423   INIT_IEEE1275_COMMON (&args.common, "enter", 0, 0);
424
425   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
426     return -1;
427   return 0;
428 }
429
430 void
431 grub_ieee1275_exit (void)
432 {
433   struct exit_args
434   {
435     struct grub_ieee1275_common_hdr common;
436   }
437   args;
438
439   INIT_IEEE1275_COMMON (&args.common, "exit", 0, 0);
440
441   IEEE1275_CALL_ENTRY_FN (&args);
442   for (;;) ;
443 }
444
445 int
446 grub_ieee1275_open (const char *path, grub_ieee1275_ihandle_t *result)
447 {
448   struct open_args
449   {
450     struct grub_ieee1275_common_hdr common;
451     grub_ieee1275_cell_t path;
452     grub_ieee1275_cell_t result;
453   }
454   args;
455
456   INIT_IEEE1275_COMMON (&args.common, "open", 1, 1);
457   args.path = (grub_ieee1275_cell_t) path;
458
459   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
460     return -1;
461   *result = args.result;
462   if (args.result == IEEE1275_IHANDLE_INVALID)
463     return -1;
464   return 0;
465 }
466
467 int
468 grub_ieee1275_close (grub_ieee1275_ihandle_t ihandle)
469 {
470   struct close_args
471   {
472     struct grub_ieee1275_common_hdr common;
473     grub_ieee1275_cell_t ihandle;
474   }
475   args;
476
477   INIT_IEEE1275_COMMON (&args.common, "close", 1, 0);
478   args.ihandle = ihandle;
479
480   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
481     return -1;
482
483   return 0;
484 }
485
486 int
487 grub_ieee1275_decode_unit4 (grub_ieee1275_ihandle_t ihandle,
488                             void *addr, grub_size_t size,
489                             grub_uint32_t *phy_lo, grub_uint32_t *phy_hi,
490                             grub_uint32_t *lun_lo, grub_uint32_t *lun_hi)
491 {
492   struct decode_args
493   {
494     struct grub_ieee1275_common_hdr common;
495     grub_ieee1275_cell_t method;
496     grub_ieee1275_cell_t ihandle;
497     grub_ieee1275_cell_t size;
498     grub_ieee1275_cell_t addr;
499     grub_ieee1275_cell_t catch_result;
500     grub_ieee1275_cell_t tgt_h;
501     grub_ieee1275_cell_t tgt_l;
502     grub_ieee1275_cell_t lun_h;
503     grub_ieee1275_cell_t lun_l;
504   }
505   args;
506
507   INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 5);
508   args.method = (grub_ieee1275_cell_t) "decode-unit";
509   args.ihandle = ihandle;
510   args.size = size;
511   args.addr = (grub_ieee1275_cell_t) addr;
512   args.catch_result = 1;
513
514   if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.catch_result))
515     {
516       grub_error (GRUB_ERR_OUT_OF_RANGE, "decode-unit failed\n");
517       return -1;
518     }
519
520   *phy_lo = args.tgt_l;
521   *phy_hi = args.tgt_h;
522   *lun_lo = args.lun_l;
523   *lun_hi = args.lun_h;
524   return 0;
525 }
526
527 char *
528 grub_ieee1275_encode_uint4 (grub_ieee1275_ihandle_t ihandle,
529                             grub_uint32_t phy_lo, grub_uint32_t phy_hi,
530                             grub_uint32_t lun_lo, grub_uint32_t lun_hi,
531                             grub_size_t *size)
532 {
533   char *addr;
534   struct encode_args
535   {
536     struct grub_ieee1275_common_hdr common;
537     grub_ieee1275_cell_t method;
538     grub_ieee1275_cell_t ihandle;
539     grub_ieee1275_cell_t tgt_h;
540     grub_ieee1275_cell_t tgt_l;
541     grub_ieee1275_cell_t lun_h;
542     grub_ieee1275_cell_t lun_l;
543     grub_ieee1275_cell_t catch_result;
544     grub_ieee1275_cell_t size;
545     grub_ieee1275_cell_t addr;
546   }
547   args;
548
549   INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 3);
550   args.method = (grub_ieee1275_cell_t) "encode-unit";
551   args.ihandle = ihandle;
552
553   args.tgt_l = phy_lo;
554   args.tgt_h = phy_hi;
555   args.lun_l = lun_lo;
556   args.lun_h = lun_hi;
557   args.catch_result = 1;
558
559   if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.catch_result))
560     {
561       grub_error (GRUB_ERR_OUT_OF_RANGE, "encode-unit failed\n");
562       return 0;
563     }
564
565   addr = (void *)args.addr;
566   *size = args.size;
567   addr = grub_strdup ((char *)args.addr);
568   return addr;
569 }
570
571 int
572 grub_ieee1275_claim (grub_addr_t addr, grub_size_t size, unsigned int align,
573                      grub_addr_t *result)
574 {
575   struct claim_args
576   {
577     struct grub_ieee1275_common_hdr common;
578     grub_ieee1275_cell_t addr;
579     grub_ieee1275_cell_t size;
580     grub_ieee1275_cell_t align;
581     grub_ieee1275_cell_t base;
582   }
583   args;
584
585   INIT_IEEE1275_COMMON (&args.common, "claim", 3, 1);
586   args.addr = (grub_ieee1275_cell_t) addr;
587   args.size = (grub_ieee1275_cell_t) size;
588   args.align = (grub_ieee1275_cell_t) align;
589
590   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
591     return -1;
592   if (result)
593     *result = args.base;
594   if (args.base == IEEE1275_CELL_INVALID)
595     return -1;
596   return 0;
597 }
598
599 int
600 grub_ieee1275_release (grub_addr_t addr, grub_size_t size)
601 {
602  struct release_args
603  {
604     struct grub_ieee1275_common_hdr common;
605     grub_ieee1275_cell_t addr;
606     grub_ieee1275_cell_t size;
607  }
608  args;
609
610   INIT_IEEE1275_COMMON (&args.common, "release", 2, 0);
611   args.addr = addr;
612   args.size = size;
613
614   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
615     return -1;
616   return 0;
617 }
618
619 int
620 grub_ieee1275_set_property (grub_ieee1275_phandle_t phandle,
621                             const char *propname, const void *buf,
622                             grub_size_t size, grub_ssize_t *actual)
623 {
624   struct set_property_args
625   {
626     struct grub_ieee1275_common_hdr common;
627     grub_ieee1275_cell_t phandle;
628     grub_ieee1275_cell_t propname;
629     grub_ieee1275_cell_t buf;
630     grub_ieee1275_cell_t size;
631     grub_ieee1275_cell_t actual;
632   }
633   args;
634
635   INIT_IEEE1275_COMMON (&args.common, "setprop", 4, 1);
636   args.size = (grub_ieee1275_cell_t) size;
637   args.buf = (grub_ieee1275_cell_t) buf;
638   args.propname = (grub_ieee1275_cell_t) propname;
639   args.phandle = (grub_ieee1275_cell_t) phandle;
640
641   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
642     return -1;
643   *actual = args.actual;
644   if ((args.actual == IEEE1275_CELL_INVALID) || (args.actual != args.size))
645     return -1;
646   return 0;
647 }
648
649 int
650 grub_ieee1275_set_color (grub_ieee1275_ihandle_t ihandle,
651                          int index, int r, int g, int b)
652 {
653   struct set_color_args
654   {
655     struct grub_ieee1275_common_hdr common;
656     grub_ieee1275_cell_t method;
657     grub_ieee1275_cell_t ihandle;
658     grub_ieee1275_cell_t index;
659     grub_ieee1275_cell_t b;
660     grub_ieee1275_cell_t g;
661     grub_ieee1275_cell_t r;
662     grub_ieee1275_cell_t catch_result;
663   }
664   args;
665
666   INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 1);
667   args.method = (grub_ieee1275_cell_t) "color!";
668   args.ihandle = ihandle;
669   args.index = index;
670   args.r = r;
671   args.g = g;
672   args.b = b;
673
674   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
675     return -1;
676   return args.catch_result;
677 }
678
679 int
680 grub_ieee1275_milliseconds (grub_uint32_t *msecs)
681 {
682   struct milliseconds_args
683   {
684     struct grub_ieee1275_common_hdr common;
685     grub_ieee1275_cell_t msecs;
686   }
687   args;
688
689   INIT_IEEE1275_COMMON (&args.common, "milliseconds", 0, 1);
690
691   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
692     return -1;
693   *msecs = args.msecs;
694   return 0;
695 }
696
697 int
698 grub_ieee1275_set_address (grub_ieee1275_ihandle_t ihandle,
699                            grub_uint32_t target, grub_uint32_t lun)
700 {
701   struct set_address
702   {
703     struct grub_ieee1275_common_hdr common;
704     grub_ieee1275_cell_t method;
705     grub_ieee1275_cell_t ihandle;
706     grub_ieee1275_cell_t tgt;
707     grub_ieee1275_cell_t lun;
708     grub_ieee1275_cell_t catch_result;
709   }
710   args;
711
712   INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 1);
713
714   /*
715    * IEEE 1275-1994 Standard for Boot (Initialization Configuration)
716    * Firmware: Core Requirements and Practices
717    * E.3.2.2 Bus-specific methods for bus nodes
718    *
719    * A package implementing the scsi-2 device type shall implement the
720    * following bus-specific method:
721    *
722    * set-address ( unit# target# -- )
723    * Sets the SCSI target number (0x0..0xf) and unit number (0..7) to which
724    * subsequent commands apply.
725    */
726   args.method = (grub_ieee1275_cell_t) "set-address";
727   args.ihandle = ihandle;
728   args.tgt = target;
729   args.lun = lun;
730
731   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
732     return -1;
733
734   return args.catch_result;
735 }
736
737 int
738 grub_ieee1275_no_data_command (grub_ieee1275_ihandle_t ihandle,
739                                const void *cmd_addr, grub_ssize_t *result)
740 {
741   struct set_address
742   {
743     struct grub_ieee1275_common_hdr common;
744     grub_ieee1275_cell_t method;
745     grub_ieee1275_cell_t ihandle;
746     grub_ieee1275_cell_t cmd_addr;
747     grub_ieee1275_cell_t error;
748     grub_ieee1275_cell_t catch_result;
749   }
750   args;
751
752   INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2);
753
754   /*
755    * IEEE 1275-1994 Standard for Boot (Initialization Configuration)
756    * Firmware: Core Requirements and Practices
757    *
758    * E.3.2.2 Bus-specific methods for bus nodes
759    *
760    * A package implementing the scsi-2 device type shall implement the
761    * following bus-specific method:
762    *
763    * no-data-command ( cmd-addr -- error? )
764    * Executes a simple SCSI command, automatically retrying under
765    * certain conditions.  cmd-addr is the address of a 6-byte command buffer
766    * containing an SCSI command that does not have a data transfer phase.
767    * Executes the command, retrying indefinitely with the same retry criteria
768    * as retry-command.
769    *
770    * error? is nonzero if an error occurred, zero otherwise.
771    * NOTE no-data-command is a convenience function. It provides
772    * no capabilities that are not present in retry-command, but for
773    * those commands that meet its restrictions, it is easier to use.
774    */
775   args.method = (grub_ieee1275_cell_t) "no-data-command";
776   args.ihandle = ihandle;
777   args.cmd_addr = (grub_ieee1275_cell_t) cmd_addr;
778
779   if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
780     return -1;
781
782   if (result)
783     *result = args.error;
784
785   return args.catch_result;
786 }
787
788 int
789 grub_ieee1275_get_block_size (grub_ieee1275_ihandle_t ihandle)
790 {
791   struct size_args_ieee1275
792     {
793       struct grub_ieee1275_common_hdr common;
794       grub_ieee1275_cell_t method;
795       grub_ieee1275_cell_t ihandle;
796       grub_ieee1275_cell_t result;
797       grub_ieee1275_cell_t size;
798     } args;
799
800   INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 2);
801   args.method = (grub_ieee1275_cell_t) "block-size";
802   args.ihandle = ihandle;
803   args.result = 1;
804
805   if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.result))
806     return 0;
807
808   return args.size;
809 }