ieee1275.c 19 KB
Newer Older
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 10
 *  (at your option) any later version.
 *
11
 *  GRUB is distributed in the hope that it will be useful,
12 13 14 15 16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  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 25
#define IEEE1275_PHANDLE_INVALID  ((grub_ieee1275_cell_t) -1)
#define IEEE1275_IHANDLE_INVALID  ((grub_ieee1275_cell_t) 0)
26
#define IEEE1275_CELL_INVALID     ((grub_ieee1275_cell_t) -1)
27

28

29 30

int
31
grub_ieee1275_finddevice (const char *name, grub_ieee1275_phandle_t *phandlep)
32
{
33 34
  struct find_device_args
  {
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 45 46

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
  *phandlep = args.phandle;
47 48
  if (args.phandle == IEEE1275_PHANDLE_INVALID)
    return -1;
49 50 51 52
  return 0;
}

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 58
  struct get_property_args
  {
59
    struct grub_ieee1275_common_hdr common;
60
    grub_ieee1275_cell_t phandle;
61 62 63 64
    grub_ieee1275_cell_t prop;
    grub_ieee1275_cell_t buf;
    grub_ieee1275_cell_t buflen;
    grub_ieee1275_cell_t size;
65 66
  }
  args;
67 68

  INIT_IEEE1275_COMMON (&args.common, "getprop", 4, 1);
69
  args.phandle = phandle;
70 71 72
  args.prop = (grub_ieee1275_cell_t) property;
  args.buf = (grub_ieee1275_cell_t) buf;
  args.buflen = (grub_ieee1275_cell_t) size;
73 74 75 76

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
  if (actual)
77
    *actual = (grub_ssize_t) args.size;
78
  if (args.size == IEEE1275_CELL_INVALID)
79
    return -1;
80 81 82
  return 0;
}

83 84 85 86 87 88 89 90 91 92 93
int
grub_ieee1275_get_integer_property (grub_ieee1275_phandle_t phandle,
				    const char *property, grub_uint32_t *buf,
				    grub_size_t size, grub_ssize_t *actual)
{
  int ret;
  ret = grub_ieee1275_get_property (phandle, property, (void *) buf, size, actual);
#ifndef GRUB_CPU_WORDS_BIGENDIAN
  /* Integer properties are always in big endian.  */
  if (ret == 0)
    {
94
      unsigned int i;
95 96 97 98 99 100 101 102
      size /= sizeof (grub_uint32_t);
      for (i = 0; i < size; i++)
	buf[i] = grub_be_to_cpu32 (buf[i]);
    }
#endif
  return ret;
}

103
int
104
grub_ieee1275_next_property (grub_ieee1275_phandle_t phandle, char *prev_prop,
105
			     char *prop)
106
{
107 108
  struct get_property_args
  {
109
    struct grub_ieee1275_common_hdr common;
110
    grub_ieee1275_cell_t phandle;
111 112 113
    grub_ieee1275_cell_t prev_prop;
    grub_ieee1275_cell_t next_prop;
    grub_ieee1275_cell_t flags;
114 115
  }
  args;
116 117

  INIT_IEEE1275_COMMON (&args.common, "nextprop", 3, 1);
118
  args.phandle = phandle;
119 120 121
  args.prev_prop = (grub_ieee1275_cell_t) prev_prop;
  args.next_prop = (grub_ieee1275_cell_t) prop;
  args.flags = (grub_ieee1275_cell_t) -1;
122 123 124

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
125
  return (int) args.flags;
126 127 128
}

int
fzielcke's avatar
fzielcke committed
129
grub_ieee1275_get_property_length (grub_ieee1275_phandle_t phandle,
130
				   const char *prop, grub_ssize_t *length)
131
{
132 133
  struct get_property_args
  {
134
    struct grub_ieee1275_common_hdr common;
135
    grub_ieee1275_cell_t phandle;
136 137
    grub_ieee1275_cell_t prop;
    grub_ieee1275_cell_t length;
138 139
  }
  args;
140 141

  INIT_IEEE1275_COMMON (&args.common, "getproplen", 2, 1);
142
  args.phandle = phandle;
143 144
  args.prop = (grub_ieee1275_cell_t) prop;
  args.length = (grub_ieee1275_cell_t) -1;
145 146 147 148

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
  *length = args.length;
149 150
  if (args.length == IEEE1275_CELL_INVALID)
    return -1;
151 152 153 154
  return 0;
}

int
155 156
grub_ieee1275_instance_to_package (grub_ieee1275_ihandle_t ihandle,
				   grub_ieee1275_phandle_t *phandlep)
157
{
158 159
  struct instance_to_package_args
  {
160
    struct grub_ieee1275_common_hdr common;
161 162
    grub_ieee1275_cell_t ihandle;
    grub_ieee1275_cell_t phandle;
163 164
  }
  args;
165 166 167

  INIT_IEEE1275_COMMON (&args.common, "instance-to-package", 1, 1);
  args.ihandle = ihandle;
fzielcke's avatar
fzielcke committed
168

169 170 171
  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
  *phandlep = args.phandle;
172 173
  if (args.phandle == IEEE1275_PHANDLE_INVALID)
    return -1;
174 175 176 177
  return 0;
}

int
178
grub_ieee1275_package_to_path (grub_ieee1275_phandle_t phandle,
179 180
			       char *path, grub_size_t len,
			       grub_ssize_t *actual)
181
{
182 183
  struct instance_to_package_args
  {
184
    struct grub_ieee1275_common_hdr common;
185
    grub_ieee1275_cell_t phandle;
186 187 188
    grub_ieee1275_cell_t buf;
    grub_ieee1275_cell_t buflen;
    grub_ieee1275_cell_t actual;
189 190
  }
  args;
191 192 193

  INIT_IEEE1275_COMMON (&args.common, "package-to-path", 3, 1);
  args.phandle = phandle;
194 195
  args.buf = (grub_ieee1275_cell_t) path;
  args.buflen = (grub_ieee1275_cell_t) len;
fzielcke's avatar
fzielcke committed
196

197 198 199 200
  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
  if (actual)
    *actual = args.actual;
201 202
  if (args.actual == IEEE1275_CELL_INVALID)
    return -1;
203 204 205 206
  return 0;
}

int
207 208
grub_ieee1275_instance_to_path (grub_ieee1275_ihandle_t ihandle,
				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 216 217
    grub_ieee1275_cell_t buf;
    grub_ieee1275_cell_t buflen;
    grub_ieee1275_cell_t actual;
218 219
  }
  args;
220 221 222

  INIT_IEEE1275_COMMON (&args.common, "instance-to-path", 3, 1);
  args.ihandle = ihandle;
223 224
  args.buf = (grub_ieee1275_cell_t) path;
  args.buflen = (grub_ieee1275_cell_t) len;
fzielcke's avatar
fzielcke committed
225

226 227 228 229
  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
  if (actual)
    *actual = args.actual;
230 231
  if (args.actual == IEEE1275_CELL_INVALID)
    return -1;
232 233 234 235
  return 0;
}

int
236
grub_ieee1275_write (grub_ieee1275_ihandle_t ihandle, const void *buffer,
237
		     grub_size_t len, grub_ssize_t *actualp)
238
{
239 240
  struct write_args
  {
241
    struct grub_ieee1275_common_hdr common;
242
    grub_ieee1275_cell_t ihandle;
243 244 245
    grub_ieee1275_cell_t buf;
    grub_ieee1275_cell_t len;
    grub_ieee1275_cell_t actual;
246 247
  }
  args;
248 249 250

  INIT_IEEE1275_COMMON (&args.common, "write", 3, 1);
  args.ihandle = ihandle;
251 252
  args.buf = (grub_ieee1275_cell_t) buffer;
  args.len = (grub_ieee1275_cell_t) len;
253 254 255 256 257 258 259 260 261

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
  if (actualp)
    *actualp = args.actual;
  return 0;
}

int
262
grub_ieee1275_read (grub_ieee1275_ihandle_t ihandle, void *buffer,
263
		    grub_size_t len, grub_ssize_t *actualp)
264
{
265 266
  struct write_args
  {
267
    struct grub_ieee1275_common_hdr common;
268
    grub_ieee1275_cell_t ihandle;
269 270 271
    grub_ieee1275_cell_t buf;
    grub_ieee1275_cell_t len;
    grub_ieee1275_cell_t actual;
272 273
  }
  args;
274 275 276

  INIT_IEEE1275_COMMON (&args.common, "read", 3, 1);
  args.ihandle = ihandle;
277 278
  args.buf = (grub_ieee1275_cell_t) buffer;
  args.len = (grub_ieee1275_cell_t) len;
279 280 281 282 283 284 285 286 287

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
  if (actualp)
    *actualp = args.actual;
  return 0;
}

int
288 289
grub_ieee1275_seek (grub_ieee1275_ihandle_t ihandle, grub_disk_addr_t pos,
		    grub_ssize_t *result)
290
{
291 292
  struct write_args
  {
293
    struct grub_ieee1275_common_hdr common;
294
    grub_ieee1275_cell_t ihandle;
295 296 297
    grub_ieee1275_cell_t pos_hi;
    grub_ieee1275_cell_t pos_lo;
    grub_ieee1275_cell_t result;
298 299
  }
  args;
300 301 302

  INIT_IEEE1275_COMMON (&args.common, "seek", 3, 1);
  args.ihandle = ihandle;
303 304 305 306 307 308 309 310 311
  /* To prevent stupid gcc warning.  */
#if GRUB_IEEE1275_CELL_SIZEOF >= 8
  args.pos_hi = 0;
  args.pos_lo = pos;
#else
  args.pos_hi = (grub_ieee1275_cell_t) (pos >> (8 * GRUB_IEEE1275_CELL_SIZEOF));
  args.pos_lo = (grub_ieee1275_cell_t) 
    (pos & ((1ULL << (8 * GRUB_IEEE1275_CELL_SIZEOF)) - 1));
#endif
312 313 314 315 316 317 318 319 320 321

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;

  if (result)
    *result = args.result;
  return 0;
}

int
322 323
grub_ieee1275_peer (grub_ieee1275_phandle_t node,
		    grub_ieee1275_phandle_t *result)
324
{
325 326
  struct peer_args
  {
327
    struct grub_ieee1275_common_hdr common;
328 329
    grub_ieee1275_cell_t node;
    grub_ieee1275_cell_t result;
330 331
  }
  args;
332 333 334 335 336 337 338

  INIT_IEEE1275_COMMON (&args.common, "peer", 1, 1);
  args.node = node;

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
  *result = args.result;
339 340
  if (args.result == 0)
    return -1;
341 342 343 344
  return 0;
}

int
345 346
grub_ieee1275_child (grub_ieee1275_phandle_t node,
		     grub_ieee1275_phandle_t *result)
347
{
348 349
  struct child_args
  {
350
    struct grub_ieee1275_common_hdr common;
351 352
    grub_ieee1275_cell_t node;
    grub_ieee1275_cell_t result;
353 354
  }
  args;
355 356 357 358 359 360 361 362

  INIT_IEEE1275_COMMON (&args.common, "child", 1, 1);
  args.node = node;
  args.result = IEEE1275_PHANDLE_INVALID;

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
  *result = args.result;
363 364
  if (args.result == 0)
    return -1;
365 366 367 368
  return 0;
}

int
369 370
grub_ieee1275_parent (grub_ieee1275_phandle_t node,
		      grub_ieee1275_phandle_t *result)
371
{
372 373
  struct parent_args
  {
374
    struct grub_ieee1275_common_hdr common;
375 376
    grub_ieee1275_cell_t node;
    grub_ieee1275_cell_t result;
377 378
  }
  args;
379 380 381 382 383 384 385 386 387 388 389

  INIT_IEEE1275_COMMON (&args.common, "parent", 1, 1);
  args.node = node;
  args.result = IEEE1275_PHANDLE_INVALID;

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
  *result = args.result;
  return 0;
}

390
int
391
grub_ieee1275_interpret (const char *command, grub_ieee1275_cell_t *catch)
392
{
393 394
  struct enter_args
  {
395
    struct grub_ieee1275_common_hdr common;
396 397
    grub_ieee1275_cell_t command;
    grub_ieee1275_cell_t catch;
398 399
  }
  args;
400

bean's avatar
bean committed
401 402 403
  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET))
    return -1;

404
  INIT_IEEE1275_COMMON (&args.common, "interpret", 1, 1);
405
  args.command = (grub_ieee1275_cell_t) command;
406 407 408 409 410 411 412 413

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
  if (catch)
    *catch = args.catch;
  return 0;
}

414 415 416
int
grub_ieee1275_enter (void)
{
417 418
  struct enter_args
  {
419
    struct grub_ieee1275_common_hdr common;
420 421
  }
  args;
422 423 424 425 426 427 428 429

  INIT_IEEE1275_COMMON (&args.common, "enter", 0, 0);

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
  return 0;
}

430
void
431
grub_ieee1275_exit (void)
432
{
433 434
  struct exit_args
  {
435
    struct grub_ieee1275_common_hdr common;
436 437
  }
  args;
438 439 440

  INIT_IEEE1275_COMMON (&args.common, "exit", 0, 0);

441 442
  IEEE1275_CALL_ENTRY_FN (&args);
  for (;;) ;
443 444 445
}

int
446
grub_ieee1275_open (const char *path, grub_ieee1275_ihandle_t *result)
447
{
448 449
  struct open_args
  {
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 460 461

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
  *result = args.result;
462 463
  if (args.result == IEEE1275_IHANDLE_INVALID)
    return -1;
464 465 466 467
  return 0;
}

int
468
grub_ieee1275_close (grub_ieee1275_ihandle_t ihandle)
469
{
470 471
  struct close_args
  {
472
    struct grub_ieee1275_common_hdr common;
473
    grub_ieee1275_cell_t ihandle;
474 475
  }
  args;
476 477 478 479 480 481 482 483 484 485

  INIT_IEEE1275_COMMON (&args.common, "close", 1, 0);
  args.ihandle = ihandle;

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;

  return 0;
}

486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
int
grub_ieee1275_decode_unit4 (grub_ieee1275_ihandle_t ihandle,
                            void *addr, grub_size_t size,
                            grub_uint32_t *phy_lo, grub_uint32_t *phy_hi,
                            grub_uint32_t *lun_lo, grub_uint32_t *lun_hi)
{
  struct decode_args
  {
    struct grub_ieee1275_common_hdr common;
    grub_ieee1275_cell_t method;
    grub_ieee1275_cell_t ihandle;
    grub_ieee1275_cell_t size;
    grub_ieee1275_cell_t addr;
    grub_ieee1275_cell_t catch_result;
    grub_ieee1275_cell_t tgt_h;
    grub_ieee1275_cell_t tgt_l;
    grub_ieee1275_cell_t lun_h;
    grub_ieee1275_cell_t lun_l;
  }
  args;

  INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 5);
  args.method = (grub_ieee1275_cell_t) "decode-unit";
  args.ihandle = ihandle;
  args.size = size;
  args.addr = (grub_ieee1275_cell_t) addr;
  args.catch_result = 1;

  if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.catch_result))
    {
      grub_error (GRUB_ERR_OUT_OF_RANGE, "decode-unit failed\n");
      return -1;
    }

  *phy_lo = args.tgt_l;
  *phy_hi = args.tgt_h;
  *lun_lo = args.lun_l;
  *lun_hi = args.lun_h;
  return 0;
}

527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
char *
grub_ieee1275_encode_uint4 (grub_ieee1275_ihandle_t ihandle,
                            grub_uint32_t phy_lo, grub_uint32_t phy_hi,
                            grub_uint32_t lun_lo, grub_uint32_t lun_hi,
                            grub_size_t *size)
{
  char *addr;
  struct encode_args
  {
    struct grub_ieee1275_common_hdr common;
    grub_ieee1275_cell_t method;
    grub_ieee1275_cell_t ihandle;
    grub_ieee1275_cell_t tgt_h;
    grub_ieee1275_cell_t tgt_l;
    grub_ieee1275_cell_t lun_h;
    grub_ieee1275_cell_t lun_l;
    grub_ieee1275_cell_t catch_result;
    grub_ieee1275_cell_t size;
    grub_ieee1275_cell_t addr;
  }
  args;

  INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 3);
  args.method = (grub_ieee1275_cell_t) "encode-unit";
  args.ihandle = ihandle;

  args.tgt_l = phy_lo;
  args.tgt_h = phy_hi;
  args.lun_l = lun_lo;
  args.lun_h = lun_hi;
  args.catch_result = 1;

  if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.catch_result))
    {
      grub_error (GRUB_ERR_OUT_OF_RANGE, "encode-unit failed\n");
      return 0;
    }

  addr = (void *)args.addr;
  *size = args.size;
  addr = grub_strdup ((char *)args.addr);
  return addr;
}

571
int
572 573
grub_ieee1275_claim (grub_addr_t addr, grub_size_t size, unsigned int align,
		     grub_addr_t *result)
574
{
575 576
  struct claim_args
  {
577
    struct grub_ieee1275_common_hdr common;
578 579 580 581
    grub_ieee1275_cell_t addr;
    grub_ieee1275_cell_t size;
    grub_ieee1275_cell_t align;
    grub_ieee1275_cell_t base;
582 583
  }
  args;
584 585

  INIT_IEEE1275_COMMON (&args.common, "claim", 3, 1);
586 587 588
  args.addr = (grub_ieee1275_cell_t) addr;
  args.size = (grub_ieee1275_cell_t) size;
  args.align = (grub_ieee1275_cell_t) align;
589 590 591

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
592 593
  if (result)
    *result = args.base;
594
  if (args.base == IEEE1275_CELL_INVALID)
595
    return -1;
596 597 598
  return 0;
}

599
int
600
grub_ieee1275_release (grub_addr_t addr, grub_size_t size)
601
{
602 603
 struct release_args
 {
604
    struct grub_ieee1275_common_hdr common;
605 606
    grub_ieee1275_cell_t addr;
    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;
fzielcke's avatar
fzielcke committed
613

614 615 616 617 618
  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
  return 0;
}

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 625
  struct set_property_args
  {
626
    struct grub_ieee1275_common_hdr common;
627
    grub_ieee1275_cell_t phandle;
628 629 630 631
    grub_ieee1275_cell_t propname;
    grub_ieee1275_cell_t buf;
    grub_ieee1275_cell_t size;
    grub_ieee1275_cell_t actual;
632 633
  }
  args;
634 635

  INIT_IEEE1275_COMMON (&args.common, "setprop", 4, 1);
636 637 638 639
  args.size = (grub_ieee1275_cell_t) size;
  args.buf = (grub_ieee1275_cell_t) buf;
  args.propname = (grub_ieee1275_cell_t) propname;
  args.phandle = (grub_ieee1275_cell_t) phandle;
640 641 642 643

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
  *actual = args.actual;
644 645
  if ((args.actual == IEEE1275_CELL_INVALID) || (args.actual != args.size))
    return -1;
646 647 648 649
  return 0;
}

int
650
grub_ieee1275_set_color (grub_ieee1275_ihandle_t ihandle,
651 652
			 int index, int r, int g, int b)
{
653 654
  struct set_color_args
  {
655
    struct grub_ieee1275_common_hdr common;
656 657
    grub_ieee1275_cell_t method;
    grub_ieee1275_cell_t ihandle;
658 659 660 661
    grub_ieee1275_cell_t index;
    grub_ieee1275_cell_t b;
    grub_ieee1275_cell_t g;
    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 669 670 671 672 673 674 675
  args.ihandle = ihandle;
  args.index = index;
  args.r = r;
  args.g = g;
  args.b = b;

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
676
  return args.catch_result;
677
}
678 679 680 681

int
grub_ieee1275_milliseconds (grub_uint32_t *msecs)
{
682 683
  struct milliseconds_args
  {
684
    struct grub_ieee1275_common_hdr common;
685
    grub_ieee1275_cell_t msecs;
686 687
  }
  args;
688 689 690 691 692 693 694 695

  INIT_IEEE1275_COMMON (&args.common, "milliseconds", 0, 1);

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;
  *msecs = args.msecs;
  return 0;
}
696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735

int
grub_ieee1275_set_address (grub_ieee1275_ihandle_t ihandle,
                           grub_uint32_t target, grub_uint32_t lun)
{
  struct set_address
  {
    struct grub_ieee1275_common_hdr common;
    grub_ieee1275_cell_t method;
    grub_ieee1275_cell_t ihandle;
    grub_ieee1275_cell_t tgt;
    grub_ieee1275_cell_t lun;
    grub_ieee1275_cell_t catch_result;
  }
  args;

  INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 1);

  /*
   * IEEE 1275-1994 Standard for Boot (Initialization Configuration)
   * Firmware: Core Requirements and Practices
   * E.3.2.2 Bus-specific methods for bus nodes
   *
   * A package implementing the scsi-2 device type shall implement the
   * following bus-specific method:
   *
   * set-address ( unit# target# -- )
   * Sets the SCSI target number (0x0..0xf) and unit number (0..7) to which
   * subsequent commands apply.
   */
  args.method = (grub_ieee1275_cell_t) "set-address";
  args.ihandle = ihandle;
  args.tgt = target;
  args.lun = lun;

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;

  return args.catch_result;
}
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786

int
grub_ieee1275_no_data_command (grub_ieee1275_ihandle_t ihandle,
                               const void *cmd_addr, grub_ssize_t *result)
{
  struct set_address
  {
    struct grub_ieee1275_common_hdr common;
    grub_ieee1275_cell_t method;
    grub_ieee1275_cell_t ihandle;
    grub_ieee1275_cell_t cmd_addr;
    grub_ieee1275_cell_t error;
    grub_ieee1275_cell_t catch_result;
  }
  args;

  INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2);

  /*
   * IEEE 1275-1994 Standard for Boot (Initialization Configuration)
   * Firmware: Core Requirements and Practices
   *
   * E.3.2.2 Bus-specific methods for bus nodes
   *
   * A package implementing the scsi-2 device type shall implement the
   * following bus-specific method:
   *
   * no-data-command ( cmd-addr -- error? )
   * Executes a simple SCSI command, automatically retrying under
   * certain conditions.  cmd-addr is the address of a 6-byte command buffer
   * containing an SCSI command that does not have a data transfer phase.
   * Executes the command, retrying indefinitely with the same retry criteria
   * as retry-command.
   *
   * error? is nonzero if an error occurred, zero otherwise.
   * NOTE no-data-command is a convenience function. It provides
   * no capabilities that are not present in retry-command, but for
   * those commands that meet its restrictions, it is easier to use.
   */
  args.method = (grub_ieee1275_cell_t) "no-data-command";
  args.ihandle = ihandle;
  args.cmd_addr = (grub_ieee1275_cell_t) cmd_addr;

  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;

  if (result)
    *result = args.error;

  return args.catch_result;
}