1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/param.h> 30*0Sstevel@tonic-gate #include <sys/promif.h> 31*0Sstevel@tonic-gate #include <sys/salib.h> 32*0Sstevel@tonic-gate /* EXPORT DELETE START */ 33*0Sstevel@tonic-gate #include <bootlog.h> 34*0Sstevel@tonic-gate /* EXPORT DELETE END */ 35*0Sstevel@tonic-gate #include "ramdisk.h" 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate /* 38*0Sstevel@tonic-gate * This is a chunk of Forth delivered by the OBP group. When loaded 39*0Sstevel@tonic-gate * into OBP it creates a ramdisk device node whose functionality is 40*0Sstevel@tonic-gate * defined in FWARC 2002/299. 41*0Sstevel@tonic-gate * 42*0Sstevel@tonic-gate * Note the %s in the line following " new-device" - this is where we 43*0Sstevel@tonic-gate * plug the name of the node in. 44*0Sstevel@tonic-gate */ 45*0Sstevel@tonic-gate static const char ramdisk_fth[] = 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate "headerless " 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate "\" /\" find-package 0= if" 50*0Sstevel@tonic-gate " .\" Can't find /\" abort " 51*0Sstevel@tonic-gate "then push-package " 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate "new-device" 54*0Sstevel@tonic-gate " \" %s\" device-name" 55*0Sstevel@tonic-gate " \" block\" encode-string \" device_type\" property" 56*0Sstevel@tonic-gate /* CSTYLED */ 57*0Sstevel@tonic-gate " \" SUNW,ramdisk\" encode-string \" compatible\" property" 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate " hex" 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gate " headerless" 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate " 0 value mmu-ihandle" 64*0Sstevel@tonic-gate " 0 value mem-ihandle" 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate " : get-memory-ihandles" /* ( -- ) */ 67*0Sstevel@tonic-gate " \" /chosen\" find-package drop dup \" mmu\" rot" 68*0Sstevel@tonic-gate " get-package-property if" 69*0Sstevel@tonic-gate " .\" Can't find chosen mmu property\" cr abort" 70*0Sstevel@tonic-gate " then" 71*0Sstevel@tonic-gate " decode-int to mmu-ihandle 2drop" 72*0Sstevel@tonic-gate " \" memory\" rot get-package-property if" 73*0Sstevel@tonic-gate " .\" Can't find chosen memory property\" cr abort" 74*0Sstevel@tonic-gate " then" 75*0Sstevel@tonic-gate " decode-int to mem-ihandle 2drop" 76*0Sstevel@tonic-gate " ;" 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate " : get-page-size" /* ( -- page-size ) */ 79*0Sstevel@tonic-gate " mmu-ihandle ihandle>phandle \" page-size\" rot get-package-property" 80*0Sstevel@tonic-gate " if h# 2000 else decode-int nip nip then " 81*0Sstevel@tonic-gate " ;" 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate " : get-mode" /* ( -- rw-mode ) */ 84*0Sstevel@tonic-gate " here \" translate\" mmu-ihandle $call-method if" 85*0Sstevel@tonic-gate " nip nip" 86*0Sstevel@tonic-gate " else" 87*0Sstevel@tonic-gate " h# 27" 88*0Sstevel@tonic-gate " then" 89*0Sstevel@tonic-gate " ;" 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate " : 64>32bit-phys" /* ( 64bit.lo 64bit.hi -- 32bit.lo 32bit.hi ) */ 92*0Sstevel@tonic-gate " drop xlsplit" 93*0Sstevel@tonic-gate " ;" 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate " : 32>64bit-phys" /* ( 32bit.lo 32bit.hi -- 64bit.lo 64bit.hi ) */ 96*0Sstevel@tonic-gate " lxjoin 0" 97*0Sstevel@tonic-gate " ;" 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate " : phy-claim" /* ( size align -- base.lo base.hi 0 | error ) */ 100*0Sstevel@tonic-gate " \" claim\" mem-ihandle ['] $call-method catch if" 101*0Sstevel@tonic-gate " drop 2drop 2drop -1" 102*0Sstevel@tonic-gate " else" 103*0Sstevel@tonic-gate " 64>32bit-phys 0" 104*0Sstevel@tonic-gate " then" 105*0Sstevel@tonic-gate " ;" 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate " : phy-release" /* ( phys.lo phys.hi size -- ) */ 108*0Sstevel@tonic-gate " >r 32>64bit-phys r> \" release\" mem-ihandle $call-method" 109*0Sstevel@tonic-gate " ;" 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate " : vir-claim" /* ( [ virt ] size align -- base ) */ 112*0Sstevel@tonic-gate " \" claim\" mmu-ihandle $call-method" 113*0Sstevel@tonic-gate " ;" 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate " : vir-release" /* ( virt size -- ) */ 116*0Sstevel@tonic-gate " \" release\" mmu-ihandle $call-method" 117*0Sstevel@tonic-gate " ;" 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate " : vir-map" /* ( phys-lo phys-hi virt size mode -- ) */ 120*0Sstevel@tonic-gate " >r >r >r 32>64bit-phys r> r> r>" 121*0Sstevel@tonic-gate " \" map\" mmu-ihandle $call-method" 122*0Sstevel@tonic-gate " ;" 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate " : vir-unmap" /* ( virt size -- ) */ 125*0Sstevel@tonic-gate " \" unmap\" mmu-ihandle $call-method" 126*0Sstevel@tonic-gate " ;" 127*0Sstevel@tonic-gate " headers" 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate /* \ This structure represents a physical "chunk" of ramdisk memory */ 130*0Sstevel@tonic-gate " struct" 131*0Sstevel@tonic-gate " /l field >res-pa.lo" /* \ lower 32bits of physical address */ 132*0Sstevel@tonic-gate " /l field >res-pa.hi" /* \ upper 32bits of physical address */ 133*0Sstevel@tonic-gate " /l field >res-len.lo" /* \ lower 32bits of chunk size */ 134*0Sstevel@tonic-gate " /l field >res-len.hi" /* \ upper 32bits of chunk size */ 135*0Sstevel@tonic-gate " constant /res-entry" 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate " 4 value max-res-entries" /* \ Max # of non-contig phys chunks */ 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate " max-res-entries /res-entry *" /* \ size of resource buffer */ 140*0Sstevel@tonic-gate " ( value ) buffer: my-resources" /* \ resource buffer label */ 141*0Sstevel@tonic-gate " 0 value num-res-entries" /* \ current # of chunks allocated */ 142*0Sstevel@tonic-gate " h# 10 constant label-size" /* \ size of disk-label buffer */ 143*0Sstevel@tonic-gate " label-size instance buffer: my-label" /* \ for disk-label argument string */ 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate " get-memory-ihandles" /* \ So we can claim/map/free memory */ 146*0Sstevel@tonic-gate " get-page-size value pagesize" /* \ get virt pagesize from vmem node */ 147*0Sstevel@tonic-gate " get-mode value mode" /* \ get mode to map virt memory with */ 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate " 0 instance value window-mapped?" /* \ just in case for pa's near 0 */ 150*0Sstevel@tonic-gate " 0 instance value window-pa" /* \ physical base of virtual window */ 151*0Sstevel@tonic-gate " 0 instance value window-base" /* \ virtual window base */ 152*0Sstevel@tonic-gate " h# 10000 constant window-size" /* \ virtual window size */ 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate " 0 instance value filepos" /* \ file position marker */ 155*0Sstevel@tonic-gate " -1 value new-disk?" /* \ need to alloc new resources? */ 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate " 0 instance value offset-low" /* \ Offset to start of partition */ 158*0Sstevel@tonic-gate " 0 instance value offset-high" /* \ For partition relative seeks */ 159*0Sstevel@tonic-gate " 0 instance value label-package" /* \ ihandle for disk-label package */ 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate " external" /* \ Because device_type = block */ 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate " 0 value size" /* \ size of disk */ 164*0Sstevel@tonic-gate " 0 value #blocks" /* \ size of disk / decimal 512 */ 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate " headerless" 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate " : round-up" /* ( n -- n' ) */ 169*0Sstevel@tonic-gate " 1- tuck + swap invert and" 170*0Sstevel@tonic-gate " ;" 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate " : init-label-package" /* ( adr len -- okay? ) */ 173*0Sstevel@tonic-gate " 0 to offset-high 0 to offset-low" 174*0Sstevel@tonic-gate " \" disk-label\" $open-package to label-package" 175*0Sstevel@tonic-gate " label-package if" 176*0Sstevel@tonic-gate " 0 0 \" offset\" label-package $call-method" 177*0Sstevel@tonic-gate " to offset-high to offset-low" 178*0Sstevel@tonic-gate " true" 179*0Sstevel@tonic-gate " else" 180*0Sstevel@tonic-gate " .\" Can't open disk label package\" cr false" 181*0Sstevel@tonic-gate " then" 182*0Sstevel@tonic-gate " ;" 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate " : res-entry-len" /* ( n -- 64bit-len | 0 ) \ Get length of chunk n */ 185*0Sstevel@tonic-gate " dup num-res-entries > if" 186*0Sstevel@tonic-gate " drop 0" 187*0Sstevel@tonic-gate " else" 188*0Sstevel@tonic-gate " /res-entry * my-resources +" 189*0Sstevel@tonic-gate " dup >res-len.lo l@ swap >res-len.hi l@" 190*0Sstevel@tonic-gate " lxjoin" 191*0Sstevel@tonic-gate " then" 192*0Sstevel@tonic-gate " ;" 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate " : res-entry-pa" /* ( n -- 64bit-pa | 0 ) \ Get phys address of chunk n */ 195*0Sstevel@tonic-gate " dup num-res-entries > if" /* ( n ) */ 196*0Sstevel@tonic-gate " drop 0" /* ( 0 ) */ 197*0Sstevel@tonic-gate " else" /* ( n ) */ 198*0Sstevel@tonic-gate " /res-entry * my-resources +" /* ( chunk-adr ) */ 199*0Sstevel@tonic-gate " dup >res-pa.lo l@ swap >res-pa.hi l@" /* ( pa.lo pa.hi ) */ 200*0Sstevel@tonic-gate " lxjoin" /* ( 64bit-pa ) */ 201*0Sstevel@tonic-gate " then" /* ( 64bit-pa ) */ 202*0Sstevel@tonic-gate " ;" 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate " : claim-window" /* ( -- ) \ Claim mem for virt window */ 205*0Sstevel@tonic-gate " window-size pagesize vir-claim to window-base" 206*0Sstevel@tonic-gate " ;" 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate " : release-window" /* ( -- ) \ Free virt window memory */ 209*0Sstevel@tonic-gate " window-base window-size" 210*0Sstevel@tonic-gate " 2dup vir-unmap" 211*0Sstevel@tonic-gate " vir-release" 212*0Sstevel@tonic-gate " ;" 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate " : map-window" /* ( 64bit-pa -- ) \ Map a physical address to the v-window */ 215*0Sstevel@tonic-gate " dup to window-pa" 216*0Sstevel@tonic-gate " xlsplit window-base window-size mode vir-map" 217*0Sstevel@tonic-gate " -1 to window-mapped?" 218*0Sstevel@tonic-gate " ;" 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate " : unmap-window" /* ( -- ) \ Unmap the virtual window */ 221*0Sstevel@tonic-gate " window-base window-size vir-unmap" 222*0Sstevel@tonic-gate " 0 to window-mapped?" 223*0Sstevel@tonic-gate " ;" 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate " : in-window?" /* ( pa -- in-window? ) */ 226*0Sstevel@tonic-gate " window-mapped? if" 227*0Sstevel@tonic-gate " window-pa dup window-size + 1- between" 228*0Sstevel@tonic-gate " else" 229*0Sstevel@tonic-gate " drop 0" 230*0Sstevel@tonic-gate " then" 231*0Sstevel@tonic-gate " ;" 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate " : window-left" /* ( offset -- space-left-in-window ) */ 234*0Sstevel@tonic-gate " window-size mod" 235*0Sstevel@tonic-gate " window-size swap -" 236*0Sstevel@tonic-gate " ;" 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate " : release-resources" /* ( -- ) \ release previously claimed phys addrs */ 239*0Sstevel@tonic-gate " num-res-entries 0 2dup = if" /* ( res-entries 0 ) */ 240*0Sstevel@tonic-gate " 2drop exit" /* ( ) */ 241*0Sstevel@tonic-gate " then" /* ( res-entries 0 ) */ 242*0Sstevel@tonic-gate " do" /* ( ) */ 243*0Sstevel@tonic-gate " i res-entry-pa xlsplit" /* ( pa.lo pa.hi ) */ 244*0Sstevel@tonic-gate " i res-entry-len phy-release" /* ( ) */ 245*0Sstevel@tonic-gate " loop" /* ( ) */ 246*0Sstevel@tonic-gate " 0 to num-res-entries" /* ( ) */ 247*0Sstevel@tonic-gate " my-resources max-res-entries /res-entry * erase" /* ( ) */ 248*0Sstevel@tonic-gate " ;" 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate " : fill-entry" /* ( pa.lo pa.hi size.lo size.hi -- ) \ fill chunk buf */ 251*0Sstevel@tonic-gate " num-res-entries /res-entry * my-resources +" 252*0Sstevel@tonic-gate " tuck >res-len.hi l!" 253*0Sstevel@tonic-gate " tuck >res-len.lo l!" 254*0Sstevel@tonic-gate " tuck >res-pa.hi l!" 255*0Sstevel@tonic-gate " >res-pa.lo l!" 256*0Sstevel@tonic-gate " num-res-entries 1+ to num-res-entries" 257*0Sstevel@tonic-gate " ;" 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate /* \ First attempt to claim the whole ramdisk contiguously. */ 260*0Sstevel@tonic-gate /* \ If that doesn't work, try to claim it in smaller chunks */ 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate " : attempt-claim" /* ( size -- error? ) */ 263*0Sstevel@tonic-gate " size 0 begin" /* ( next totcl ) */ 264*0Sstevel@tonic-gate " over pagesize phy-claim if" /* ( next totcl ) */ 265*0Sstevel@tonic-gate " swap 2 / window-size" /* ( totcl next' ) */ 266*0Sstevel@tonic-gate " round-up swap" /* ( next' totcl ) */ 267*0Sstevel@tonic-gate " else" /* ( next totcl pa.lo,hi ) */ 268*0Sstevel@tonic-gate " 2over drop xlsplit" /* ( next totcl pa.lo,hi len.lo,hi ) */ 269*0Sstevel@tonic-gate " fill-entry" /* ( next totcl ) */ 270*0Sstevel@tonic-gate " over +" /* ( next totcl ) */ 271*0Sstevel@tonic-gate " then" /* ( next totcl ) */ 272*0Sstevel@tonic-gate " 2dup size - 0>=" /* ( next totcl next comp? ) */ 273*0Sstevel@tonic-gate " swap size max-res-entries /" /* ( next totcl comp? next smallest ) */ 274*0Sstevel@tonic-gate " - 0< or" /* ( next totcl ) */ 275*0Sstevel@tonic-gate " until" /* ( next totcl ) */ 276*0Sstevel@tonic-gate " nip size - 0< if -1 else 0 then" 277*0Sstevel@tonic-gate " ;" 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate " : claim-resources" /* ( -- error? ) */ 280*0Sstevel@tonic-gate " attempt-claim if release-resources -1 else 0 then" 281*0Sstevel@tonic-gate " ;" 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate /* \ Given a 0-relative disk offset compute the proper physical address */ 284*0Sstevel@tonic-gate " : offset>pa" /* ( disk-offset -- 64bit-pa error? ) */ 285*0Sstevel@tonic-gate " 0 num-res-entries 0 do" /* ( disk-offset 0 ) */ 286*0Sstevel@tonic-gate " i res-entry-len +" /* ( disk-offset len' ) */ 287*0Sstevel@tonic-gate " 2dup - 0< if" /* ( disk-offset len' ) */ 288*0Sstevel@tonic-gate " - i res-entry-len +" /* ( offset-into-pa ) \ briefly -ve */ 289*0Sstevel@tonic-gate " i res-entry-pa + 0" /* ( pa 0 ) */ 290*0Sstevel@tonic-gate " unloop exit" /* ( pa 0 ) */ 291*0Sstevel@tonic-gate " then" /* ( disk-offset len' ) */ 292*0Sstevel@tonic-gate " loop" /* ( disk-offset len' ) */ 293*0Sstevel@tonic-gate " drop -1" /* ( offset error ) */ 294*0Sstevel@tonic-gate " ;" 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate /* \ Map the virtual window to the physical-address corresponding to the */ 297*0Sstevel@tonic-gate /* \ given 0-relative disk offset */ 298*0Sstevel@tonic-gate " : get-window" /* ( offset -- va len error? ) */ 299*0Sstevel@tonic-gate " dup offset>pa if" /* ( offset pa ) */ 300*0Sstevel@tonic-gate " -1" /* ( offset pa -1 ) */ 301*0Sstevel@tonic-gate " else" /* ( offset pa ) */ 302*0Sstevel@tonic-gate " dup in-window? 0= if" /* ( offset pa ) */ 303*0Sstevel@tonic-gate " unmap-window" /* ( offset pa ) */ 304*0Sstevel@tonic-gate " over window-size mod - map-window" /* ( offset ) */ 305*0Sstevel@tonic-gate " else" 306*0Sstevel@tonic-gate " drop" 307*0Sstevel@tonic-gate " then" 308*0Sstevel@tonic-gate " window-base over window-size mod +" /* ( offset va ) */ 309*0Sstevel@tonic-gate " swap window-left 0" /* ( va len 0 ) */ 310*0Sstevel@tonic-gate " then" /* ( va len error? ) */ 311*0Sstevel@tonic-gate " ;" 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate " headers" 314*0Sstevel@tonic-gate 315*0Sstevel@tonic-gate /* \ Write len1 bytes from src into va. */ 316*0Sstevel@tonic-gate " : partial-write" /* ( src len0 va len1 -- len' ) */ 317*0Sstevel@tonic-gate " rot min dup >r move r>" 318*0Sstevel@tonic-gate " ;" 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate /* \ Read len1 bytes from src into va. */ 321*0Sstevel@tonic-gate " : partial-read" /* ( src len0 va len1 -- len' ) */ 322*0Sstevel@tonic-gate " rot min dup >r >r swap r> move r>" 323*0Sstevel@tonic-gate " ;" 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate " defer operation ' partial-write is operation" 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate /* \ Write or Read len given the src address. The block-operation word */ 328*0Sstevel@tonic-gate /* \ determines the physical address that corresponds to the current file */ 329*0Sstevel@tonic-gate /* \ position, and maps/unmaps the 64K virtual window */ 330*0Sstevel@tonic-gate " : block-operation" /* ( src len acf -- len' ) */ 331*0Sstevel@tonic-gate " is operation" 332*0Sstevel@tonic-gate " 0 -rot begin" /* ( 0 src len ) */ 333*0Sstevel@tonic-gate " dup 0>" /* ( len' src len more? ) */ 334*0Sstevel@tonic-gate " while" /* ( len' src len ) */ 335*0Sstevel@tonic-gate " 2dup filepos" /* ( len' src len src len filepos ) */ 336*0Sstevel@tonic-gate " get-window if" /* ( len' src len src len va len ) */ 337*0Sstevel@tonic-gate " 2drop 2drop 2drop exit" /* ( len' ) */ 338*0Sstevel@tonic-gate " then" /* ( len src len src len va len ) */ 339*0Sstevel@tonic-gate " operation" /* ( len src len len' ) */ 340*0Sstevel@tonic-gate " dup filepos + to filepos" /* ( len src len len' ) */ 341*0Sstevel@tonic-gate " >r r@ - rot r@ + rot r> + rot" /* ( len' src' len' ) */ 342*0Sstevel@tonic-gate " repeat" /* ( len' src' len' ) */ 343*0Sstevel@tonic-gate " 2drop" /* ( len' ) */ 344*0Sstevel@tonic-gate " ;" 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gate " : range-bad?" /* ( adr -- range-bad? ) */ 347*0Sstevel@tonic-gate " 0 size between 0=" 348*0Sstevel@tonic-gate " ;" 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate " : space-left" /* ( -- space-left ) */ 351*0Sstevel@tonic-gate " size filepos -" 352*0Sstevel@tonic-gate " ;" 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate " : hex-number" /* ( adr,len -- true | n false ) */ 355*0Sstevel@tonic-gate " base @ >r hex $number r> base !" 356*0Sstevel@tonic-gate " ;" 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate " : parse-size" /* ( $nums -- 64bit-size | 0 ) \ poss ',' seperated ints */ 359*0Sstevel@tonic-gate " ascii , left-parse-string" /* ( $num $num ) */ 360*0Sstevel@tonic-gate " hex-number if 2drop 0 exit then" /* ( $num n ) */ 361*0Sstevel@tonic-gate " over 0= if nip nip exit then" /* ( $num n ) */ 362*0Sstevel@tonic-gate " -rot hex-number if drop 0 exit then" /* ( hi lo ) */ 363*0Sstevel@tonic-gate " swap lxjoin" 364*0Sstevel@tonic-gate " ;" 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate " : set-size" /* ( adr len -- error? ) */ 367*0Sstevel@tonic-gate " parse-size dup 0= if" /* ( size ) */ 368*0Sstevel@tonic-gate " drop -1" /* ( -1 ) */ 369*0Sstevel@tonic-gate " else" /* ( size ) */ 370*0Sstevel@tonic-gate " window-size round-up" /* ( size' ) */ 371*0Sstevel@tonic-gate " dup to size" /* ( size' ) */ 372*0Sstevel@tonic-gate " d# 512 / to #blocks" /* ( ) */ 373*0Sstevel@tonic-gate " \" nolabel\" my-label pack" /* \ first open cannot have a label */ 374*0Sstevel@tonic-gate " drop 0" /* ( 0 ) */ 375*0Sstevel@tonic-gate " then" /* ( error? ) */ 376*0Sstevel@tonic-gate " ;" 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate " : $=" /* (s adr1 len1 adr2 len2 -- same? ) */ 379*0Sstevel@tonic-gate " rot tuck <> if 3drop false exit then" /* ( adr1 adr2 len1 ) */ 380*0Sstevel@tonic-gate " comp 0=" /* ( same? ) */ 381*0Sstevel@tonic-gate " ;" 382*0Sstevel@tonic-gate 383*0Sstevel@tonic-gate " : is-label?" /* ( adr len -- is-label? ) \ $= "nolabel" or <a-z> */ 384*0Sstevel@tonic-gate " dup 1 = if" /* ( adr len ) */ 385*0Sstevel@tonic-gate " drop c@ ascii a ascii z between" /* ( is-label? ) */ 386*0Sstevel@tonic-gate " else" /* ( adr len ) */ 387*0Sstevel@tonic-gate " \" nolabel\" $=" /* ( is-label? ) */ 388*0Sstevel@tonic-gate " then" /* ( is-label? ) */ 389*0Sstevel@tonic-gate " ;" 390*0Sstevel@tonic-gate 391*0Sstevel@tonic-gate " : set-label" /* ( adr len -- error? ) */ 392*0Sstevel@tonic-gate " my-label label-size erase" 393*0Sstevel@tonic-gate " dup 1+ label-size > if" 394*0Sstevel@tonic-gate " 2drop -1" 395*0Sstevel@tonic-gate " else" 396*0Sstevel@tonic-gate " my-label pack drop 0" 397*0Sstevel@tonic-gate " then" 398*0Sstevel@tonic-gate " ;" 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate " : process-args" /* ( arg$ -- error? ) */ 401*0Sstevel@tonic-gate " ascii = left-parse-string" /* ( value$ key$ ) */ 402*0Sstevel@tonic-gate " new-disk? if" /* ( value$ key$ ) */ 403*0Sstevel@tonic-gate " 2dup \" size\" $= if" /* ( value$ key$ ) */ 404*0Sstevel@tonic-gate " 2drop set-size exit" /* ( error? ) */ 405*0Sstevel@tonic-gate " then" /* ( value$ key$ ) */ 406*0Sstevel@tonic-gate " else" /* ( value$ key$ ) */ 407*0Sstevel@tonic-gate " 2dup is-label? if" /* ( value$ key$ ) */ 408*0Sstevel@tonic-gate " 2swap 2drop set-label exit" /* ( error? ) */ 409*0Sstevel@tonic-gate " then" /* ( value$ key$ ) */ 410*0Sstevel@tonic-gate " then" /* ( value$ key$ ) */ 411*0Sstevel@tonic-gate " .\" Inappropriate argument \" type cr 2drop -1" /* ( -1 ) */ 412*0Sstevel@tonic-gate " ;" 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate /* \ Publish the physical chunks that make up the ramdisk in the */ 415*0Sstevel@tonic-gate /* \ existing property */ 416*0Sstevel@tonic-gate " : create-existing-prop" /* ( -- ) */ 417*0Sstevel@tonic-gate " 0 0 encode-bytes" /* ( adr 0 ) */ 418*0Sstevel@tonic-gate " num-res-entries 0 do" /* ( adr 0 ) */ 419*0Sstevel@tonic-gate " i /res-entry * my-resources + >r" /* ( adr len ) */ 420*0Sstevel@tonic-gate " r@ >res-pa.hi l@ encode-int encode+" /* ( adr len ) */ 421*0Sstevel@tonic-gate " r@ >res-pa.lo l@ encode-int encode+" /* ( adr len ) */ 422*0Sstevel@tonic-gate " r@ >res-len.hi l@ encode-int encode+" /* ( adr len ) */ 423*0Sstevel@tonic-gate " r> >res-len.lo l@ encode-int encode+" /* ( adr len ) */ 424*0Sstevel@tonic-gate " loop" /* ( adr len ) */ 425*0Sstevel@tonic-gate " \" existing\" property" /* ( ) */ 426*0Sstevel@tonic-gate " ;" 427*0Sstevel@tonic-gate 428*0Sstevel@tonic-gate " external" 429*0Sstevel@tonic-gate 430*0Sstevel@tonic-gate " : read" /* ( adr,len -- len' ) */ 431*0Sstevel@tonic-gate " space-left" /* ( adr len space-left ) */ 432*0Sstevel@tonic-gate " min ['] partial-read" /* ( adr len' read-acf ) */ 433*0Sstevel@tonic-gate " block-operation" /* ( len' ) */ 434*0Sstevel@tonic-gate " ;" 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate " : write" /* ( adr,len -- len' ) */ 437*0Sstevel@tonic-gate " space-left" /* ( adr len space-left ) */ 438*0Sstevel@tonic-gate " min ['] partial-write" /* ( adr len' write-acf ) */ 439*0Sstevel@tonic-gate " block-operation" /* ( len' ) */ 440*0Sstevel@tonic-gate " ;" 441*0Sstevel@tonic-gate 442*0Sstevel@tonic-gate " : seek" /* ( offset other -- error? ) */ 443*0Sstevel@tonic-gate " offset-high + swap offset-low + swap drop" /* \ "other" arg unused */ 444*0Sstevel@tonic-gate " dup 0< if" /* ( offset ) */ 445*0Sstevel@tonic-gate " size +" /* ( offset' ) */ 446*0Sstevel@tonic-gate " then" /* ( offset' ) */ 447*0Sstevel@tonic-gate " 0 + dup range-bad? if" /* ( offset' ) */ 448*0Sstevel@tonic-gate " drop -1" /* ( -1 ) */ 449*0Sstevel@tonic-gate " else" /* ( offset' ) */ 450*0Sstevel@tonic-gate " to filepos false" /* ( 0 ) */ 451*0Sstevel@tonic-gate " then" /* ( error? ) */ 452*0Sstevel@tonic-gate " ;" 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gate " : load" /* ( addr -- size ) */ 455*0Sstevel@tonic-gate " \" load\" label-package $call-method" 456*0Sstevel@tonic-gate " ;" 457*0Sstevel@tonic-gate 458*0Sstevel@tonic-gate " : offset" /* ( rel -- abs ) \ needed for device_type = block */ 459*0Sstevel@tonic-gate " offset-low +" 460*0Sstevel@tonic-gate " ;" 461*0Sstevel@tonic-gate 462*0Sstevel@tonic-gate /* \ release resources, initialize data, remove existing property */ 463*0Sstevel@tonic-gate /* \ Can be called with no instance data */ 464*0Sstevel@tonic-gate " : destroy" /* ( -- ) */ 465*0Sstevel@tonic-gate " \" existing\" delete-property" 466*0Sstevel@tonic-gate " 0 to size" 467*0Sstevel@tonic-gate " -1 to new-disk?" 468*0Sstevel@tonic-gate " release-resources" 469*0Sstevel@tonic-gate " ;" 470*0Sstevel@tonic-gate 471*0Sstevel@tonic-gate " : open" /* ( -- flag ) */ 472*0Sstevel@tonic-gate " my-args process-args if" 473*0Sstevel@tonic-gate " 0 exit" /* \ unrecognized arguments */ 474*0Sstevel@tonic-gate " then" 475*0Sstevel@tonic-gate " new-disk? if" 476*0Sstevel@tonic-gate " claim-resources if 0 exit then" /* \ can't claim */ 477*0Sstevel@tonic-gate " create-existing-prop" /* \ advertise resources */ 478*0Sstevel@tonic-gate " 0 to new-disk?" /* \ no longer a new-disk */ 479*0Sstevel@tonic-gate " then" 480*0Sstevel@tonic-gate " claim-window" /* \ claim virtual window */ 481*0Sstevel@tonic-gate " my-label count init-label-package 0= if 0 exit then" 482*0Sstevel@tonic-gate " -1" 483*0Sstevel@tonic-gate " ;" 484*0Sstevel@tonic-gate 485*0Sstevel@tonic-gate " : close" /* ( -- ) */ 486*0Sstevel@tonic-gate " window-base if " 487*0Sstevel@tonic-gate " release-window" 488*0Sstevel@tonic-gate " then" 489*0Sstevel@tonic-gate " ; " 490*0Sstevel@tonic-gate "finish-device " 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate "pop-package" 493*0Sstevel@tonic-gate 494*0Sstevel@tonic-gate ; /* end of ramdisk_fth[] initialization */ 495*0Sstevel@tonic-gate 496*0Sstevel@tonic-gate 497*0Sstevel@tonic-gate /* 498*0Sstevel@tonic-gate * Create an actual ramdisk instance. 499*0Sstevel@tonic-gate */ 500*0Sstevel@tonic-gate static void 501*0Sstevel@tonic-gate create_ramdisk_node(const char *ramdisk_name) 502*0Sstevel@tonic-gate { 503*0Sstevel@tonic-gate char *fth_buf; 504*0Sstevel@tonic-gate size_t buf_size; 505*0Sstevel@tonic-gate 506*0Sstevel@tonic-gate buf_size = sizeof (ramdisk_fth) + strlen(ramdisk_name); 507*0Sstevel@tonic-gate 508*0Sstevel@tonic-gate fth_buf = bkmem_alloc(buf_size); 509*0Sstevel@tonic-gate if (fth_buf == NULL) { 510*0Sstevel@tonic-gate prom_panic("unable to allocate Forth buffer for ramdisk"); 511*0Sstevel@tonic-gate } 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate (void) snprintf(fth_buf, buf_size, ramdisk_fth, ramdisk_name); 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate prom_interpret(fth_buf, 0, 0, 0, 0, 0); 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate bkmem_free(fth_buf, buf_size); 518*0Sstevel@tonic-gate } 519*0Sstevel@tonic-gate 520*0Sstevel@tonic-gate int 521*0Sstevel@tonic-gate create_ramdisk(const char *ramdisk_name, size_t size, char **device_path) 522*0Sstevel@tonic-gate { 523*0Sstevel@tonic-gate static int first_time = 1; 524*0Sstevel@tonic-gate char buf[OBP_MAXPATHLEN]; 525*0Sstevel@tonic-gate ihandle_t ih; 526*0Sstevel@tonic-gate 527*0Sstevel@tonic-gate /* 528*0Sstevel@tonic-gate * Ensure that size is a multiple of page size (rounded up). 529*0Sstevel@tonic-gate */ 530*0Sstevel@tonic-gate size = ptob(btopr(size)); 531*0Sstevel@tonic-gate 532*0Sstevel@tonic-gate /* EXPORT DELETE START */ 533*0Sstevel@tonic-gate bootlog("wanboot", BOOTLOG_VERBOSE, "Creating ramdisk, size=0x%lx", 534*0Sstevel@tonic-gate size); 535*0Sstevel@tonic-gate /* EXPORT DELETE END */ 536*0Sstevel@tonic-gate 537*0Sstevel@tonic-gate if (strcmp(ramdisk_name, RD_ROOTFS) == 0 || 538*0Sstevel@tonic-gate strcmp(ramdisk_name, RD_BOOTFS) == 0) { 539*0Sstevel@tonic-gate 540*0Sstevel@tonic-gate if (first_time) { 541*0Sstevel@tonic-gate first_time = 0; 542*0Sstevel@tonic-gate 543*0Sstevel@tonic-gate create_ramdisk_node(RD_ROOTFS); 544*0Sstevel@tonic-gate create_ramdisk_node(RD_BOOTFS); 545*0Sstevel@tonic-gate } 546*0Sstevel@tonic-gate 547*0Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "/%s:nolabel", ramdisk_name); 548*0Sstevel@tonic-gate *device_path = strdup(buf); 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate if (*device_path != NULL) { 551*0Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "/%s:size=%x,%x", 552*0Sstevel@tonic-gate ramdisk_name, 553*0Sstevel@tonic-gate (uint32_t)(size >> 32), (uint32_t)size); 554*0Sstevel@tonic-gate 555*0Sstevel@tonic-gate if ((ih = prom_open(buf)) != 0) { 556*0Sstevel@tonic-gate return (ih); 557*0Sstevel@tonic-gate } 558*0Sstevel@tonic-gate } 559*0Sstevel@tonic-gate } 560*0Sstevel@tonic-gate 561*0Sstevel@tonic-gate /* EXPORT DELETE START */ 562*0Sstevel@tonic-gate bootlog("wanboot", BOOTLOG_CRIT, "Cannot create ramdisk \"%s\"", 563*0Sstevel@tonic-gate ramdisk_name); 564*0Sstevel@tonic-gate /* EXPORT DELETE END */ 565*0Sstevel@tonic-gate prom_panic("create_ramdisk: fatal error"); 566*0Sstevel@tonic-gate /* NOTREACHED */ 567*0Sstevel@tonic-gate } 568