ofw_real.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
  1. /* $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $ */
  2. /*-
  3. * SPDX-License-Identifier:BSD-4-Clause AND BSD-2-Clause-FreeBSD
  4. *
  5. * Copyright (C) 1995, 1996 Wolfgang Solfrank.
  6. * Copyright (C) 1995, 1996 TooLs GmbH.
  7. * All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. All advertising materials mentioning features or use of this software
  18. * must display the following acknowledgement:
  19. * This product includes software developed by TooLs GmbH.
  20. * 4. The name of TooLs GmbH may not be used to endorse or promote products
  21. * derived from this software without specific prior written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
  24. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  25. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  26. * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  27. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  28. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  29. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  30. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  31. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  32. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. /*-
  35. * Copyright (C) 2000 Benno Rice.
  36. * All rights reserved.
  37. *
  38. * Redistribution and use in source and binary forms, with or without
  39. * modification, are permitted provided that the following conditions
  40. * are met:
  41. * 1. Redistributions of source code must retain the above copyright
  42. * notice, this list of conditions and the following disclaimer.
  43. * 2. Redistributions in binary form must reproduce the above copyright
  44. * notice, this list of conditions and the following disclaimer in the
  45. * documentation and/or other materials provided with the distribution.
  46. *
  47. * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
  48. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  49. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  50. * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  51. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  52. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  53. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  54. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  55. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  56. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  57. */
  58. #include <sys/cdefs.h>
  59. __FBSDID("$FreeBSD$");
  60. #include <sys/endian.h>
  61. #include <sys/param.h>
  62. #include <sys/kernel.h>
  63. #include <sys/lock.h>
  64. #include <sys/mutex.h>
  65. #include <sys/systm.h>
  66. #include <vm/vm.h>
  67. #include <vm/vm_page.h>
  68. #include <vm/pmap.h>
  69. #include <machine/bus.h>
  70. #include <machine/md_var.h>
  71. #include <machine/ofw_machdep.h>
  72. #include <machine/stdarg.h>
  73. #include <dev/ofw/openfirm.h>
  74. #include <dev/ofw/ofwvar.h>
  75. #include "ofw_if.h"
  76. static int ofw_real_init(ofw_t, void *openfirm);
  77. static int ofw_real_test(ofw_t, const char *name);
  78. static phandle_t ofw_real_peer(ofw_t, phandle_t node);
  79. static phandle_t ofw_real_child(ofw_t, phandle_t node);
  80. static phandle_t ofw_real_parent(ofw_t, phandle_t node);
  81. static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance);
  82. static ssize_t ofw_real_getproplen(ofw_t, phandle_t package,
  83. const char *propname);
  84. static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname,
  85. void *buf, size_t buflen);
  86. static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous,
  87. char *buf, size_t);
  88. static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname,
  89. const void *buf, size_t len);
  90. static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len);
  91. static phandle_t ofw_real_finddevice(ofw_t, const char *device);
  92. static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf,
  93. size_t len);
  94. static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf,
  95. size_t len);
  96. static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method,
  97. int nargs, int nreturns, cell_t *args_and_returns);
  98. static int ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns,
  99. cell_t *returns);
  100. static ihandle_t ofw_real_open(ofw_t, const char *device);
  101. static void ofw_real_close(ofw_t, ihandle_t instance);
  102. static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len);
  103. static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr,
  104. size_t len);
  105. static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos);
  106. static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align);
  107. static void ofw_real_release(ofw_t, void *virt, size_t size);
  108. static void ofw_real_enter(ofw_t);
  109. static void ofw_real_exit(ofw_t);
  110. static ofw_method_t ofw_real_methods[] = {
  111. OFWMETHOD(ofw_init, ofw_real_init),
  112. OFWMETHOD(ofw_peer, ofw_real_peer),
  113. OFWMETHOD(ofw_child, ofw_real_child),
  114. OFWMETHOD(ofw_parent, ofw_real_parent),
  115. OFWMETHOD(ofw_instance_to_package, ofw_real_instance_to_package),
  116. OFWMETHOD(ofw_getproplen, ofw_real_getproplen),
  117. OFWMETHOD(ofw_getprop, ofw_real_getprop),
  118. OFWMETHOD(ofw_nextprop, ofw_real_nextprop),
  119. OFWMETHOD(ofw_setprop, ofw_real_setprop),
  120. OFWMETHOD(ofw_canon, ofw_real_canon),
  121. OFWMETHOD(ofw_finddevice, ofw_real_finddevice),
  122. OFWMETHOD(ofw_instance_to_path, ofw_real_instance_to_path),
  123. OFWMETHOD(ofw_package_to_path, ofw_real_package_to_path),
  124. OFWMETHOD(ofw_test, ofw_real_test),
  125. OFWMETHOD(ofw_call_method, ofw_real_call_method),
  126. OFWMETHOD(ofw_interpret, ofw_real_interpret),
  127. OFWMETHOD(ofw_open, ofw_real_open),
  128. OFWMETHOD(ofw_close, ofw_real_close),
  129. OFWMETHOD(ofw_read, ofw_real_read),
  130. OFWMETHOD(ofw_write, ofw_real_write),
  131. OFWMETHOD(ofw_seek, ofw_real_seek),
  132. OFWMETHOD(ofw_claim, ofw_real_claim),
  133. OFWMETHOD(ofw_release, ofw_real_release),
  134. OFWMETHOD(ofw_enter, ofw_real_enter),
  135. OFWMETHOD(ofw_exit, ofw_real_exit),
  136. { 0, 0 }
  137. };
  138. static ofw_def_t ofw_real = {
  139. OFW_STD_REAL,
  140. ofw_real_methods,
  141. 0
  142. };
  143. OFW_DEF(ofw_real);
  144. static ofw_def_t ofw_32bit = {
  145. OFW_STD_32BIT,
  146. ofw_real_methods,
  147. 0
  148. };
  149. OFW_DEF(ofw_32bit);
  150. static MALLOC_DEFINE(M_OFWREAL, "ofwreal",
  151. "Open Firmware Real Mode Bounce Page");
  152. static int (*openfirmware)(void *);
  153. static vm_offset_t of_bounce_phys;
  154. static caddr_t of_bounce_virt;
  155. static off_t of_bounce_offset;
  156. static size_t of_bounce_size;
  157. #define IN(x) htobe32(x)
  158. #define OUT(x) be32toh(x)
  159. /*
  160. * To be able to use OFW console on PPC, that requires real mode OFW,
  161. * the mutex that guards the mapping/unmapping of virtual to physical
  162. * buffers (of_real_mtx) must be of SPIN type. This is needed because
  163. * kernel console first locks a SPIN mutex before calling OFW real.
  164. * By default, of_real_mtx is a sleepable mutex. To make it of SPIN
  165. * type, use the following tunnable:
  166. * machdep.ofw.mtx_spin=1
  167. *
  168. * Besides that, a few more tunables are needed to select and use the
  169. * OFW console with real mode OFW.
  170. *
  171. * In order to disable the use of OFW FrameBuffer and fallback to the
  172. * OFW console, use:
  173. * hw.ofwfb.disable=1
  174. *
  175. * To disable the use of FDT (that doesn't support OFW read/write methods)
  176. * and use real OFW instead, unset the following loader variable:
  177. * unset usefdt
  178. *
  179. * OFW is put in quiesce state in early kernel boot, which usually disables
  180. * OFW read/write capabilities (in QEMU write continue to work, but
  181. * read doesn't). To avoid OFW quiesce, use:
  182. * debug.quiesce_ofw=0
  183. *
  184. * Note that disabling OFW quiesce can cause conflicts between kernel and
  185. * OFW trying to control the same hardware. Thus, it must be used with care.
  186. * Some conflicts can be avoided by disabling kernel drivers with hints.
  187. * For instance, to disable a xhci controller and an USB keyboard connected
  188. * to it, that may be already being used for input by OFW, use:
  189. * hint.xhci.0.disabled=1
  190. */
  191. static struct mtx of_bounce_mtx;
  192. static struct mtx of_spin_mtx;
  193. static struct mtx *of_real_mtx;
  194. static void (*of_mtx_lock)(void);
  195. static void (*of_mtx_unlock)(void);
  196. extern int ofw_real_mode;
  197. /*
  198. * After the VM is up, allocate a wired, low memory bounce page.
  199. */
  200. static void ofw_real_bounce_alloc(void *);
  201. SYSINIT(ofw_real_bounce_alloc, SI_SUB_KMEM, SI_ORDER_ANY,
  202. ofw_real_bounce_alloc, NULL);
  203. static void
  204. ofw_real_mtx_lock_spin(void)
  205. {
  206. mtx_lock_spin(of_real_mtx);
  207. }
  208. static void
  209. ofw_real_mtx_lock(void)
  210. {
  211. mtx_lock(of_real_mtx);
  212. }
  213. static void
  214. ofw_real_mtx_unlock_spin(void)
  215. {
  216. mtx_unlock_spin(of_real_mtx);
  217. }
  218. static void
  219. ofw_real_mtx_unlock(void)
  220. {
  221. mtx_unlock(of_real_mtx);
  222. }
  223. static void
  224. ofw_real_start(void)
  225. {
  226. (*of_mtx_lock)();
  227. of_bounce_offset = 0;
  228. }
  229. static void
  230. ofw_real_stop(void)
  231. {
  232. (*of_mtx_unlock)();
  233. }
  234. static void
  235. ofw_real_bounce_alloc(void *junk)
  236. {
  237. caddr_t temp;
  238. /*
  239. * Check that ofw_real is actually in use before allocating wads
  240. * of memory. Do this by checking if our mutex has been set up.
  241. */
  242. if (!mtx_initialized(&of_bounce_mtx))
  243. return;
  244. /*
  245. * Allocate a page of contiguous, wired physical memory that can
  246. * fit into a 32-bit address space and accessed from real mode.
  247. */
  248. temp = contigmalloc(4 * PAGE_SIZE, M_OFWREAL, 0, 0,
  249. ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT), PAGE_SIZE,
  250. 4 * PAGE_SIZE);
  251. if (temp == NULL)
  252. panic("%s: Not able to allocated contiguous memory\n", __func__);
  253. mtx_lock(&of_bounce_mtx);
  254. of_bounce_virt = temp;
  255. of_bounce_phys = vtophys(of_bounce_virt);
  256. of_bounce_size = 4 * PAGE_SIZE;
  257. /*
  258. * For virtual-mode OF, direct map this physical address so that
  259. * we have a 32-bit virtual address to give OF.
  260. */
  261. if (!ofw_real_mode && (!hw_direct_map || DMAP_BASE_ADDRESS != 0))
  262. pmap_kenter(of_bounce_phys, of_bounce_phys);
  263. mtx_unlock(&of_bounce_mtx);
  264. }
  265. static cell_t
  266. ofw_real_map(const void *buf, size_t len)
  267. {
  268. static char emergency_buffer[255];
  269. cell_t phys;
  270. mtx_assert(of_real_mtx, MA_OWNED);
  271. if (of_bounce_virt == NULL) {
  272. /*
  273. * If we haven't set up the MMU, then buf is guaranteed
  274. * to be accessible to OF, because the only memory we
  275. * can use right now is memory mapped by firmware.
  276. */
  277. if (!pmap_bootstrapped)
  278. return (cell_t)((uintptr_t)buf & ~DMAP_BASE_ADDRESS);
  279. /*
  280. * XXX: It is possible for us to get called before the VM has
  281. * come online, but after the MMU is up. We don't have the
  282. * bounce buffer yet, but can no longer presume a 1:1 mapping.
  283. * Copy into the emergency buffer, and reset at the end.
  284. */
  285. of_bounce_virt = emergency_buffer;
  286. of_bounce_phys = (vm_offset_t)of_bounce_virt &
  287. ~DMAP_BASE_ADDRESS;
  288. of_bounce_size = sizeof(emergency_buffer);
  289. }
  290. /*
  291. * Make sure the bounce page offset satisfies any reasonable
  292. * alignment constraint.
  293. */
  294. of_bounce_offset += sizeof(register_t) -
  295. (of_bounce_offset % sizeof(register_t));
  296. if (of_bounce_offset + len > of_bounce_size) {
  297. panic("Oversize Open Firmware call!");
  298. return 0;
  299. }
  300. if (buf != NULL)
  301. memcpy(of_bounce_virt + of_bounce_offset, buf, len);
  302. else
  303. return (0);
  304. phys = of_bounce_phys + of_bounce_offset;
  305. of_bounce_offset += len;
  306. return (phys);
  307. }
  308. static void
  309. ofw_real_unmap(cell_t physaddr, void *buf, size_t len)
  310. {
  311. mtx_assert(of_real_mtx, MA_OWNED);
  312. if (of_bounce_virt == NULL)
  313. return;
  314. if (physaddr == 0)
  315. return;
  316. memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len);
  317. }
  318. /* Initialiser */
  319. static int
  320. ofw_real_init(ofw_t ofw, void *openfirm)
  321. {
  322. int mtx_spin;
  323. openfirmware = (int (*)(void *))openfirm;
  324. mtx_init(&of_bounce_mtx, "OF Bounce Page", NULL, MTX_DEF);
  325. mtx_spin = 0;
  326. TUNABLE_INT_FETCH("machdep.ofw.mtx_spin", &mtx_spin);
  327. if (mtx_spin) {
  328. mtx_init(&of_spin_mtx, "OF Real", NULL, MTX_SPIN);
  329. of_real_mtx = &of_spin_mtx;
  330. of_mtx_lock = ofw_real_mtx_lock_spin;
  331. of_mtx_unlock = ofw_real_mtx_unlock_spin;
  332. } else {
  333. of_real_mtx = &of_bounce_mtx;
  334. of_mtx_lock = ofw_real_mtx_lock;
  335. of_mtx_unlock = ofw_real_mtx_unlock;
  336. }
  337. of_bounce_virt = NULL;
  338. return (0);
  339. }
  340. /*
  341. * Generic functions
  342. */
  343. /* Test to see if a service exists. */
  344. static int
  345. ofw_real_test(ofw_t ofw, const char *name)
  346. {
  347. vm_offset_t argsptr;
  348. struct {
  349. cell_t name;
  350. cell_t nargs;
  351. cell_t nreturns;
  352. cell_t service;
  353. cell_t missing;
  354. } args;
  355. args.name = IN((cell_t)(uintptr_t)"test");
  356. args.nargs = IN(1);
  357. args.nreturns = IN(1);
  358. ofw_real_start();
  359. args.service = IN(ofw_real_map(name, strlen(name) + 1));
  360. argsptr = ofw_real_map(&args, sizeof(args));
  361. if (args.service == 0 || openfirmware((void *)argsptr) == -1) {
  362. ofw_real_stop();
  363. return (-1);
  364. }
  365. ofw_real_unmap(argsptr, &args, sizeof(args));
  366. ofw_real_stop();
  367. return (OUT(args.missing));
  368. }
  369. /*
  370. * Device tree functions
  371. */
  372. /* Return the next sibling of this node or 0. */
  373. static phandle_t
  374. ofw_real_peer(ofw_t ofw, phandle_t node)
  375. {
  376. vm_offset_t argsptr;
  377. struct {
  378. cell_t name;
  379. cell_t nargs;
  380. cell_t nreturns;
  381. cell_t node;
  382. cell_t next;
  383. } args;
  384. args.name = IN((cell_t)(uintptr_t)"peer");
  385. args.nargs = IN(1);
  386. args.nreturns = IN(1);
  387. args.node = IN(node);
  388. ofw_real_start();
  389. argsptr = ofw_real_map(&args, sizeof(args));
  390. if (openfirmware((void *)argsptr) == -1) {
  391. ofw_real_stop();
  392. return (0);
  393. }
  394. ofw_real_unmap(argsptr, &args, sizeof(args));
  395. ofw_real_stop();
  396. return (OUT(args.next));
  397. }
  398. /* Return the first child of this node or 0. */
  399. static phandle_t
  400. ofw_real_child(ofw_t ofw, phandle_t node)
  401. {
  402. vm_offset_t argsptr;
  403. struct {
  404. cell_t name;
  405. cell_t nargs;
  406. cell_t nreturns;
  407. cell_t node;
  408. cell_t child;
  409. } args;
  410. args.name = IN((cell_t)(uintptr_t)"child");
  411. args.nargs = IN(1);
  412. args.nreturns = IN(1);
  413. args.node = IN(node);
  414. ofw_real_start();
  415. argsptr = ofw_real_map(&args, sizeof(args));
  416. if (openfirmware((void *)argsptr) == -1) {
  417. ofw_real_stop();
  418. return (0);
  419. }
  420. ofw_real_unmap(argsptr, &args, sizeof(args));
  421. ofw_real_stop();
  422. return (OUT(args.child));
  423. }
  424. /* Return the parent of this node or 0. */
  425. static phandle_t
  426. ofw_real_parent(ofw_t ofw, phandle_t node)
  427. {
  428. vm_offset_t argsptr;
  429. struct {
  430. cell_t name;
  431. cell_t nargs;
  432. cell_t nreturns;
  433. cell_t node;
  434. cell_t parent;
  435. } args;
  436. args.name = IN((cell_t)(uintptr_t)"parent");
  437. args.nargs = IN(1);
  438. args.nreturns = IN(1);
  439. args.node = IN(node);
  440. ofw_real_start();
  441. argsptr = ofw_real_map(&args, sizeof(args));
  442. if (openfirmware((void *)argsptr) == -1) {
  443. ofw_real_stop();
  444. return (0);
  445. }
  446. ofw_real_unmap(argsptr, &args, sizeof(args));
  447. ofw_real_stop();
  448. return (OUT(args.parent));
  449. }
  450. /* Return the package handle that corresponds to an instance handle. */
  451. static phandle_t
  452. ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance)
  453. {
  454. vm_offset_t argsptr;
  455. struct {
  456. cell_t name;
  457. cell_t nargs;
  458. cell_t nreturns;
  459. cell_t instance;
  460. cell_t package;
  461. } args;
  462. args.name = IN((cell_t)(uintptr_t)"instance-to-package");
  463. args.nargs = IN(1);
  464. args.nreturns = IN(1);
  465. args.instance = IN(instance);
  466. ofw_real_start();
  467. argsptr = ofw_real_map(&args, sizeof(args));
  468. if (openfirmware((void *)argsptr) == -1) {
  469. ofw_real_stop();
  470. return (-1);
  471. }
  472. ofw_real_unmap(argsptr, &args, sizeof(args));
  473. ofw_real_stop();
  474. return (OUT(args.package));
  475. }
  476. /* Get the length of a property of a package. */
  477. static ssize_t
  478. ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname)
  479. {
  480. vm_offset_t argsptr;
  481. struct {
  482. cell_t name;
  483. cell_t nargs;
  484. cell_t nreturns;
  485. cell_t package;
  486. cell_t propname;
  487. int32_t proplen;
  488. } args;
  489. args.name = IN((cell_t)(uintptr_t)"getproplen");
  490. args.nargs = IN(2);
  491. args.nreturns = IN(1);
  492. ofw_real_start();
  493. args.package = IN(package);
  494. args.propname = IN(ofw_real_map(propname, strlen(propname) + 1));
  495. argsptr = ofw_real_map(&args, sizeof(args));
  496. if (args.propname == 0 || openfirmware((void *)argsptr) == -1) {
  497. ofw_real_stop();
  498. return (-1);
  499. }
  500. ofw_real_unmap(argsptr, &args, sizeof(args));
  501. ofw_real_stop();
  502. return ((ssize_t)(int32_t)OUT(args.proplen));
  503. }
  504. /* Get the value of a property of a package. */
  505. static ssize_t
  506. ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
  507. size_t buflen)
  508. {
  509. vm_offset_t argsptr;
  510. struct {
  511. cell_t name;
  512. cell_t nargs;
  513. cell_t nreturns;
  514. cell_t package;
  515. cell_t propname;
  516. cell_t buf;
  517. cell_t buflen;
  518. int32_t size;
  519. } args;
  520. args.name = IN((cell_t)(uintptr_t)"getprop");
  521. args.nargs = IN(4);
  522. args.nreturns = IN(1);
  523. ofw_real_start();
  524. args.package = IN(package);
  525. args.propname = IN(ofw_real_map(propname, strlen(propname) + 1));
  526. args.buf = IN(ofw_real_map(buf, buflen));
  527. args.buflen = IN(buflen);
  528. argsptr = ofw_real_map(&args, sizeof(args));
  529. if (args.propname == 0 || args.buf == 0 ||
  530. openfirmware((void *)argsptr) == -1) {
  531. ofw_real_stop();
  532. return (-1);
  533. }
  534. ofw_real_unmap(argsptr, &args, sizeof(args));
  535. ofw_real_unmap(OUT(args.buf), buf, buflen);
  536. ofw_real_stop();
  537. return ((ssize_t)(int32_t)OUT(args.size));
  538. }
  539. /* Get the next property of a package. */
  540. static int
  541. ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous,
  542. char *buf, size_t size)
  543. {
  544. vm_offset_t argsptr;
  545. struct {
  546. cell_t name;
  547. cell_t nargs;
  548. cell_t nreturns;
  549. cell_t package;
  550. cell_t previous;
  551. cell_t buf;
  552. cell_t flag;
  553. } args;
  554. args.name = IN((cell_t)(uintptr_t)"nextprop");
  555. args.nargs = IN(3);
  556. args.nreturns = IN(1);
  557. ofw_real_start();
  558. args.package = IN(package);
  559. args.previous = IN(ofw_real_map(previous, (previous != NULL) ? (strlen(previous) + 1) : 0));
  560. args.buf = IN(ofw_real_map(buf, size));
  561. argsptr = ofw_real_map(&args, sizeof(args));
  562. if (args.buf == 0 || openfirmware((void *)argsptr) == -1) {
  563. ofw_real_stop();
  564. return (-1);
  565. }
  566. ofw_real_unmap(argsptr, &args, sizeof(args));
  567. ofw_real_unmap(OUT(args.buf), buf, size);
  568. ofw_real_stop();
  569. return (OUT(args.flag));
  570. }
  571. /* Set the value of a property of a package. */
  572. /* XXX Has a bug on FirePower */
  573. static int
  574. ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname,
  575. const void *buf, size_t len)
  576. {
  577. vm_offset_t argsptr;
  578. struct {
  579. cell_t name;
  580. cell_t nargs;
  581. cell_t nreturns;
  582. cell_t package;
  583. cell_t propname;
  584. cell_t buf;
  585. cell_t len;
  586. cell_t size;
  587. } args;
  588. args.name = IN((cell_t)(uintptr_t)"setprop");
  589. args.nargs = IN(4);
  590. args.nreturns = IN(1);
  591. ofw_real_start();
  592. args.package = IN(package);
  593. args.propname = IN(ofw_real_map(propname, strlen(propname) + 1));
  594. args.buf = IN(ofw_real_map(buf, len));
  595. args.len = IN(len);
  596. argsptr = ofw_real_map(&args, sizeof(args));
  597. if (args.propname == 0 || args.buf == 0 ||
  598. openfirmware((void *)argsptr) == -1) {
  599. ofw_real_stop();
  600. return (-1);
  601. }
  602. ofw_real_unmap(argsptr, &args, sizeof(args));
  603. ofw_real_stop();
  604. return (OUT(args.size));
  605. }
  606. /* Convert a device specifier to a fully qualified pathname. */
  607. static ssize_t
  608. ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len)
  609. {
  610. vm_offset_t argsptr;
  611. struct {
  612. cell_t name;
  613. cell_t nargs;
  614. cell_t nreturns;
  615. cell_t device;
  616. cell_t buf;
  617. cell_t len;
  618. int32_t size;
  619. } args;
  620. args.name = IN((cell_t)(uintptr_t)"canon");
  621. args.nargs = IN(3);
  622. args.nreturns = IN(1);
  623. ofw_real_start();
  624. args.device = IN(ofw_real_map(device, strlen(device) + 1));
  625. args.buf = IN(ofw_real_map(buf, len));
  626. args.len = IN(len);
  627. argsptr = ofw_real_map(&args, sizeof(args));
  628. if (args.device == 0 || args.buf == 0 ||
  629. openfirmware((void *)argsptr) == -1) {
  630. ofw_real_stop();
  631. return (-1);
  632. }
  633. ofw_real_unmap(argsptr, &args, sizeof(args));
  634. ofw_real_unmap(OUT(args.buf), buf, len);
  635. ofw_real_stop();
  636. return ((ssize_t)(int32_t)OUT(args.size));
  637. }
  638. /* Return a package handle for the specified device. */
  639. static phandle_t
  640. ofw_real_finddevice(ofw_t ofw, const char *device)
  641. {
  642. vm_offset_t argsptr;
  643. struct {
  644. cell_t name;
  645. cell_t nargs;
  646. cell_t nreturns;
  647. cell_t device;
  648. cell_t package;
  649. } args;
  650. args.name = IN((cell_t)(uintptr_t)"finddevice");
  651. args.nargs = IN(1);
  652. args.nreturns = IN(1);
  653. ofw_real_start();
  654. args.device = IN(ofw_real_map(device, strlen(device) + 1));
  655. argsptr = ofw_real_map(&args, sizeof(args));
  656. if (args.device == 0 ||
  657. openfirmware((void *)argsptr) == -1) {
  658. ofw_real_stop();
  659. return (-1);
  660. }
  661. ofw_real_unmap(argsptr, &args, sizeof(args));
  662. ofw_real_stop();
  663. return (OUT(args.package));
  664. }
  665. /* Return the fully qualified pathname corresponding to an instance. */
  666. static ssize_t
  667. ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
  668. {
  669. vm_offset_t argsptr;
  670. struct {
  671. cell_t name;
  672. cell_t nargs;
  673. cell_t nreturns;
  674. cell_t instance;
  675. cell_t buf;
  676. cell_t len;
  677. int32_t size;
  678. } args;
  679. args.name = IN((cell_t)(uintptr_t)"instance-to-path");
  680. args.nargs = IN(3);
  681. args.nreturns = IN(1);
  682. ofw_real_start();
  683. args.instance = IN(instance);
  684. args.buf = IN(ofw_real_map(buf, len));
  685. args.len = IN(len);
  686. argsptr = ofw_real_map(&args, sizeof(args));
  687. if (args.buf == 0 ||
  688. openfirmware((void *)argsptr) == -1) {
  689. ofw_real_stop();
  690. return (-1);
  691. }
  692. ofw_real_unmap(argsptr, &args, sizeof(args));
  693. ofw_real_unmap(OUT(args.buf), buf, len);
  694. ofw_real_stop();
  695. return ((ssize_t)(int32_t)OUT(args.size));
  696. }
  697. /* Return the fully qualified pathname corresponding to a package. */
  698. static ssize_t
  699. ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
  700. {
  701. vm_offset_t argsptr;
  702. struct {
  703. cell_t name;
  704. cell_t nargs;
  705. cell_t nreturns;
  706. cell_t package;
  707. cell_t buf;
  708. cell_t len;
  709. int32_t size;
  710. } args;
  711. args.name = IN((cell_t)(uintptr_t)"package-to-path");
  712. args.nargs = IN(3);
  713. args.nreturns = IN(1);
  714. ofw_real_start();
  715. args.package = IN(package);
  716. args.buf = IN(ofw_real_map(buf, len));
  717. args.len = IN(len);
  718. argsptr = ofw_real_map(&args, sizeof(args));
  719. if (args.buf == 0 ||
  720. openfirmware((void *)argsptr) == -1) {
  721. ofw_real_stop();
  722. return (-1);
  723. }
  724. ofw_real_unmap(argsptr, &args, sizeof(args));
  725. ofw_real_unmap(OUT(args.buf), buf, len);
  726. ofw_real_stop();
  727. return ((ssize_t)(int32_t)OUT(args.size));
  728. }
  729. /* Call the method in the scope of a given instance. */
  730. static int
  731. ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method,
  732. int nargs, int nreturns, cell_t *args_and_returns)
  733. {
  734. vm_offset_t argsptr;
  735. struct {
  736. cell_t name;
  737. cell_t nargs;
  738. cell_t nreturns;
  739. cell_t method;
  740. cell_t instance;
  741. cell_t args_n_results[12];
  742. } args;
  743. cell_t *ap, *cp;
  744. int n;
  745. args.name = IN((cell_t)(uintptr_t)"call-method");
  746. args.nargs = IN(2);
  747. args.nreturns = IN(1);
  748. if (nargs > 6)
  749. return (-1);
  750. ofw_real_start();
  751. args.nargs = IN(nargs + 2);
  752. args.nreturns = IN(nreturns + 1);
  753. args.method = IN(ofw_real_map(method, strlen(method) + 1));
  754. args.instance = IN(instance);
  755. ap = args_and_returns;
  756. for (cp = args.args_n_results + (n = nargs); --n >= 0;)
  757. *--cp = IN(*(ap++));
  758. argsptr = ofw_real_map(&args, sizeof(args));
  759. if (args.method == 0 ||
  760. openfirmware((void *)argsptr) == -1) {
  761. ofw_real_stop();
  762. return (-1);
  763. }
  764. ofw_real_unmap(argsptr, &args, sizeof(args));
  765. ofw_real_stop();
  766. if (OUT(args.args_n_results[nargs]))
  767. return (OUT(args.args_n_results[nargs]));
  768. for (cp = args.args_n_results + nargs + (n = OUT(args.nreturns)); --n > 0;)
  769. *(ap++) = OUT(*--cp);
  770. return (0);
  771. }
  772. static int
  773. ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, cell_t *returns)
  774. {
  775. vm_offset_t argsptr;
  776. struct {
  777. cell_t name;
  778. cell_t nargs;
  779. cell_t nreturns;
  780. cell_t slot[16];
  781. } args;
  782. cell_t status;
  783. int i = 0, j = 0;
  784. args.name = IN((cell_t)(uintptr_t)"interpret");
  785. args.nargs = IN(1);
  786. ofw_real_start();
  787. args.nreturns = IN(++nreturns);
  788. args.slot[i++] = IN(ofw_real_map(cmd, strlen(cmd) + 1));
  789. argsptr = ofw_real_map(&args, sizeof(args));
  790. if (openfirmware((void *)argsptr) == -1) {
  791. ofw_real_stop();
  792. return (-1);
  793. }
  794. ofw_real_unmap(argsptr, &args, sizeof(args));
  795. ofw_real_stop();
  796. status = OUT(args.slot[i++]);
  797. while (i < 1 + nreturns)
  798. returns[j++] = OUT(args.slot[i++]);
  799. return (status);
  800. }
  801. /*
  802. * Device I/O functions
  803. */
  804. /* Open an instance for a device. */
  805. static ihandle_t
  806. ofw_real_open(ofw_t ofw, const char *device)
  807. {
  808. vm_offset_t argsptr;
  809. struct {
  810. cell_t name;
  811. cell_t nargs;
  812. cell_t nreturns;
  813. cell_t device;
  814. cell_t instance;
  815. } args;
  816. args.name = IN((cell_t)(uintptr_t)"open");
  817. args.nargs = IN(1);
  818. args.nreturns = IN(1);
  819. ofw_real_start();
  820. args.device = IN(ofw_real_map(device, strlen(device) + 1));
  821. argsptr = ofw_real_map(&args, sizeof(args));
  822. if (args.device == 0 || openfirmware((void *)argsptr) == -1
  823. || args.instance == 0) {
  824. ofw_real_stop();
  825. return (-1);
  826. }
  827. ofw_real_unmap(argsptr, &args, sizeof(args));
  828. ofw_real_stop();
  829. return (OUT(args.instance));
  830. }
  831. /* Close an instance. */
  832. static void
  833. ofw_real_close(ofw_t ofw, ihandle_t instance)
  834. {
  835. vm_offset_t argsptr;
  836. struct {
  837. cell_t name;
  838. cell_t nargs;
  839. cell_t nreturns;
  840. cell_t instance;
  841. } args;
  842. args.name = IN((cell_t)(uintptr_t)"close");
  843. args.nargs = IN(1);
  844. args.nreturns = IN(0);
  845. args.instance = IN(instance);
  846. ofw_real_start();
  847. argsptr = ofw_real_map(&args, sizeof(args));
  848. openfirmware((void *)argsptr);
  849. ofw_real_stop();
  850. }
  851. /* Read from an instance. */
  852. static ssize_t
  853. ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
  854. {
  855. vm_offset_t argsptr;
  856. struct {
  857. cell_t name;
  858. cell_t nargs;
  859. cell_t nreturns;
  860. cell_t instance;
  861. cell_t addr;
  862. cell_t len;
  863. int32_t actual;
  864. } args;
  865. args.name = IN((cell_t)(uintptr_t)"read");
  866. args.nargs = IN(3);
  867. args.nreturns = IN(1);
  868. ofw_real_start();
  869. args.instance = IN(instance);
  870. args.addr = IN(ofw_real_map(addr, len));
  871. args.len = IN(len);
  872. argsptr = ofw_real_map(&args, sizeof(args));
  873. if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
  874. ofw_real_stop();
  875. return (-1);
  876. }
  877. ofw_real_unmap(argsptr, &args, sizeof(args));
  878. ofw_real_unmap(OUT(args.addr), addr, len);
  879. ofw_real_stop();
  880. return ((ssize_t)(int32_t)OUT(args.actual));
  881. }
  882. /* Write to an instance. */
  883. static ssize_t
  884. ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
  885. {
  886. vm_offset_t argsptr;
  887. struct {
  888. cell_t name;
  889. cell_t nargs;
  890. cell_t nreturns;
  891. cell_t instance;
  892. cell_t addr;
  893. cell_t len;
  894. int32_t actual;
  895. } args;
  896. args.name = IN((cell_t)(uintptr_t)"write");
  897. args.nargs = IN(3);
  898. args.nreturns = IN(1);
  899. ofw_real_start();
  900. args.instance = IN(instance);
  901. args.addr = IN(ofw_real_map(addr, len));
  902. args.len = IN(len);
  903. argsptr = ofw_real_map(&args, sizeof(args));
  904. if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
  905. ofw_real_stop();
  906. return (-1);
  907. }
  908. ofw_real_unmap(argsptr, &args, sizeof(args));
  909. ofw_real_stop();
  910. return ((ssize_t)(int32_t)OUT(args.actual));
  911. }
  912. /* Seek to a position. */
  913. static int
  914. ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos)
  915. {
  916. vm_offset_t argsptr;
  917. struct {
  918. cell_t name;
  919. cell_t nargs;
  920. cell_t nreturns;
  921. cell_t instance;
  922. cell_t poshi;
  923. cell_t poslo;
  924. cell_t status;
  925. } args;
  926. args.name = IN((cell_t)(uintptr_t)"seek");
  927. args.nargs = IN(3);
  928. args.nreturns = IN(1);
  929. args.instance = IN(instance);
  930. args.poshi = IN(pos >> 32);
  931. args.poslo = IN(pos);
  932. ofw_real_start();
  933. argsptr = ofw_real_map(&args, sizeof(args));
  934. if (openfirmware((void *)argsptr) == -1) {
  935. ofw_real_stop();
  936. return (-1);
  937. }
  938. ofw_real_unmap(argsptr, &args, sizeof(args));
  939. ofw_real_stop();
  940. return (OUT(args.status));
  941. }
  942. /*
  943. * Memory functions
  944. */
  945. /* Claim an area of memory. */
  946. static caddr_t
  947. ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align)
  948. {
  949. vm_offset_t argsptr;
  950. struct {
  951. cell_t name;
  952. cell_t nargs;
  953. cell_t nreturns;
  954. cell_t virt;
  955. cell_t size;
  956. cell_t align;
  957. cell_t baseaddr;
  958. } args;
  959. args.name = IN((cell_t)(uintptr_t)"claim");
  960. args.nargs = IN(3);
  961. args.nreturns = IN(1);
  962. args.virt = IN((cell_t)(uintptr_t)virt);
  963. args.size = IN(size);
  964. args.align = IN(align);
  965. ofw_real_start();
  966. argsptr = ofw_real_map(&args, sizeof(args));
  967. if (openfirmware((void *)argsptr) == -1) {
  968. ofw_real_stop();
  969. return ((void *)-1);
  970. }
  971. ofw_real_unmap(argsptr, &args, sizeof(args));
  972. ofw_real_stop();
  973. return ((void *)(uintptr_t)(OUT(args.baseaddr)));
  974. }
  975. /* Release an area of memory. */
  976. static void
  977. ofw_real_release(ofw_t ofw, void *virt, size_t size)
  978. {
  979. vm_offset_t argsptr;
  980. struct {
  981. cell_t name;
  982. cell_t nargs;
  983. cell_t nreturns;
  984. cell_t virt;
  985. cell_t size;
  986. } args;
  987. args.name = IN((cell_t)(uintptr_t)"release");
  988. args.nargs = IN(2);
  989. args.nreturns = IN(0);
  990. args.virt = IN((cell_t)(uintptr_t)virt);
  991. args.size = IN(size);
  992. ofw_real_start();
  993. argsptr = ofw_real_map(&args, sizeof(args));
  994. openfirmware((void *)argsptr);
  995. ofw_real_stop();
  996. }
  997. /*
  998. * Control transfer functions
  999. */
  1000. /* Suspend and drop back to the Open Firmware interface. */
  1001. static void
  1002. ofw_real_enter(ofw_t ofw)
  1003. {
  1004. vm_offset_t argsptr;
  1005. struct {
  1006. cell_t name;
  1007. cell_t nargs;
  1008. cell_t nreturns;
  1009. } args;
  1010. args.name = IN((cell_t)(uintptr_t)"enter");
  1011. args.nargs = IN(0);
  1012. args.nreturns = IN(0);
  1013. ofw_real_start();
  1014. argsptr = ofw_real_map(&args, sizeof(args));
  1015. openfirmware((void *)argsptr);
  1016. /* We may come back. */
  1017. ofw_real_stop();
  1018. }
  1019. /* Shut down and drop back to the Open Firmware interface. */
  1020. static void
  1021. ofw_real_exit(ofw_t ofw)
  1022. {
  1023. vm_offset_t argsptr;
  1024. struct {
  1025. cell_t name;
  1026. cell_t nargs;
  1027. cell_t nreturns;
  1028. } args;
  1029. args.name = IN((cell_t)(uintptr_t)"exit");
  1030. args.nargs = IN(0);
  1031. args.nreturns = IN(0);
  1032. ofw_real_start();
  1033. argsptr = ofw_real_map(&args, sizeof(args));
  1034. openfirmware((void *)argsptr);
  1035. for (;;) /* just in case */
  1036. ;
  1037. ofw_real_stop();
  1038. }