sdcmos 9.77 KB
Newer Older
Ben Avison's avatar
Ben Avison committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
;
; CDDL HEADER START
;
; The contents of this file are subject to the terms of the
; Common Development and Distribution License (the "Licence").
; You may not use this file except in compliance with the Licence.
;
; You can obtain a copy of the licence at
; cddl/RiscOS/Sources/FileSys/SDFS/SDFS/LICENCE.
; See the Licence for the specific language governing permissions
; and limitations under the Licence.
;
; When distributing Covered Code, include this CDDL HEADER in each
; file and include the Licence file. If applicable, add the
; following below this CDDL HEADER, with the fields enclosed by
; brackets "[]" replaced with your own identifying information:
; Portions Copyright [yyyy] [name of copyright owner]
;
; CDDL HEADER END
;
; Copyright 2012 Ben Avison.  All rights reserved.
22
; Portions Copyright 2012 Jeffrey Lee.
Ben Avison's avatar
Ben Avison committed
23 24 25
; Use is subject to license terms.
;

26 27 28 29 30
 [ :LNOT::DEF: StoreInHAL
        GBLL    StoreInHAL
StoreInHAL SETL {FALSE};
 ]

Ben Avison's avatar
Ben Avison committed
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
        GET     ListOpts
        GET     Macros
        GET     System
        GET     Proc
        GET     HighFSI
        GET     ModHand
        GET     OsBytes
        GET     FileTypes
        GET     VersionASM

        AREA    |Asm$$Code|, CODE, READONLY, PIC

        ENTRY

        DCD     0 ; Start
        DCD     Init - |Asm$$Code|
        DCD     Final - |Asm$$Code|
        DCD     0; Service call handler
        DCD     Title - |Asm$$Code|
        DCD     Help - |Asm$$Code|
        DCD     0 ; Keyword table
        DCD     0 ; SWI chunk
        DCD     0 ; SWI handler
        DCD     0 ; SWI table
        DCD     0 ; SWI decoder
        DCD     0 ; Messages
        DCD     Flags - |Asm$$Code|

Title   =       Module_ComponentName, 0
Help    =       Module_ComponentName, 9, 9, Module_HelpVersion, 0
        ALIGN
Flags   &       ModuleFlag_32bit

64 65 66 67 68 69 70 71 72 73 74
 [ StoreInHAL

NonCanonicalisedPath
        =       "SDFS::0.$.!Boot.Loader.riscos/img", 0
        ALIGN

CMOSMarker UND  #&C305
OSIm    =       "OSIm"

 |

Ben Avison's avatar
Ben Avison committed
75 76
NonCanonicalisedPath
        =       "SDFS::0.$.CMOS", 0
77 78
NonCanonicalisedPath2
        =       "SDFS::0.$.!Boot.Loader.CMOS", 0
Ben Avison's avatar
Ben Avison committed
79 80 81 82 83 84 85
        ALIGN

SaveCMOS
        =       "SaveCMOS "
Len_SaveCMOS * .-SaveCMOS
        ALIGN

86 87
 ]

Ben Avison's avatar
Ben Avison committed
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
Init    ROUT
        Entry
        ; This module is designed to be included in a ROM, in which case we have
        ; to take account of the fact that SDFS::0 isn't properly initialised
        ; until the callbacks after ROM init.
        ADR     r0, CallBackFromInit
        MOV     r1, r12
        SWI     XOS_AddCallBack
        EXIT

CallBackFromInit ROUT
        Push    "lr" ; separate instructions to reduce warnings
        ADD     lr, sp, #4
        Push    "r0-r6, lr" ; yes, need to stack sp

        ; We assume that we're entered during or soon after boot. In which case,
        ; if there is an SD card inserted, and if it contains a file called
        ; "CMOS" in its root directory of the correct filetype, then we must
        ; assume that it could have been used to initialise the kernel's CMOS
        ; RAM cache, and therefore needs updating whenever someone writes CMOS.

109 110 111 112 113 114 115 116 117
        ADR     r1, NonCanonicalisedPath
        BL      TryInit

      [ :LNOT: StoreInHAL
        ; Also try !Boot.Loader.CMOS, to allow the special FAT-in-Filecore
        ; partition formats to be used on machines other than the Raspberry Pi
        ADRVS   r1, NonCanonicalisedPath2
        BLVS    TryInit
      ]
118
        BVS     %FT90
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154

        ; All good - get on ByteV
        MOV     r0, #ByteV
        ADR     r1, MyByteV
        MOV     r2, r12
        SWI     XOS_Claim
        BVS     %F90
        Pull    "r0-r6, lr" ; separate instructions to reduce warnings
        Pull    "pc"

90      ; Error detected during callback - kill the module and exit
        ASSERT  %F99-%F98 = 8
        ADR     r0, %F98
        LDMIA   r0, {r1-r2}
        Push    "r1-r2"
        MOV     r0, #1
        MOV     r1, sp
        ADD     r2, sp, #%F99-%F98-1
        SWI     XOS_SynchroniseCodeAreas
        MOV     r0, #ModHandReason_Delete
        ADR     r1, Title
        ADD     r2, sp, #%F99-%F98 ; point r2 at stack frame
        MOV     pc, sp
        ; This last bit is executed after the module is killed so can't safely
        ; be executed in place - do it from the stack instead
98      SWI     XOS_Module
        LDMIA   r2, {r0-r6, sp, pc} ; atomic update of sp (which makes this code volatile) with pc
99


; In: r1 = filename
; Out: Regs corrupt
;      V set on failure
;      No error pointer returned
TryInit ROUT
        Entry
Ben Avison's avatar
Ben Avison committed
155 156 157 158 159 160 161 162 163
        ; Find how long the canonicalised name is
        MOV     r0, #FSControl_CanonicalisePath
        MOV     r2, #0
        MOV     r3, #0
        MOV     r4, #0
        MOV     r5, #0
        SWI     XOS_FSControl
        BVS     %F90

164 165 166 167
      [ StoreInHAL
        ; Allocate a buffer to hold filename of the ROM image plus terminator
        RSB     r3, r5, #1
      |
Ben Avison's avatar
Ben Avison committed
168 169 170
        ; Allocate a buffer for the command string - will contain "SaveCMOS "
        ; plus the canonicalised name of the file, plus a terminator
        RSB     r3, r5, #Len_SaveCMOS + 1
171 172
      ]
        MOV     r0, #ModHandReason_Claim
Ben Avison's avatar
Ben Avison committed
173 174 175 176 177
        SWI     XOS_Module
        BVS     %F90
        STR     r2, [r12]

        ; Get the canonicalised name
178
      [ :LNOT: StoreInHAL
Ben Avison's avatar
Ben Avison committed
179
        ADD     r2, r2, #Len_SaveCMOS
180
      ]
Ben Avison's avatar
Ben Avison committed
181 182 183 184 185 186
        MOV     r5, r3
        MOV     r0, #FSControl_CanonicalisePath
        MOV     r3, #0
        SWI     XOS_FSControl
        BVS     %F90

187
      [ :LNOT: StoreInHAL
Ben Avison's avatar
Ben Avison committed
188 189 190 191 192 193 194 195
        ; Copy in the "SaveCMOS " part now we have a few more working registers
        ASSERT  Len_SaveCMOS = 9
        SUB     r2, r2, #Len_SaveCMOS
        ADR     r3, SaveCMOS
        LDMIA   r3!, {r4-r5}
        LDRB    r6, [r3]
        STMIA   r2!, {r4-r5}
        STRB    r6, [r2], #1
196
      ]
Ben Avison's avatar
Ben Avison committed
197

198
        ; Check it's a file (or image file)
Ben Avison's avatar
Ben Avison committed
199 200 201 202 203 204
        MOV     r0, #OSFile_ReadWithTypeNoPath
        MOV     r1, r2
        SWI     XOS_File
        BVS     %F90
        TST     r0, #object_file
        BEQ     %F90
205 206 207

      [ :LNOT: StoreInHAL
        ; Check it's a sensible filetype
Ben Avison's avatar
Ben Avison committed
208 209
        LDR     r0, =FileType_Configuration
        TEQ     r6, r0
210 211
        LDRNE   r0, =FileType_MSDOS
        TEQNE   r6, r0
Ben Avison's avatar
Ben Avison committed
212
        BNE     %F90
213
      ]
214 215 216
        ; All good
        CLRV
        EXIT
Ben Avison's avatar
Ben Avison committed
217

218 219 220 221 222 223 224 225 226 227 228
90
        ; Something went wrong
        ; Free our workspace to avoid potential leak if TryInit called multiple times
        LDR     r2, [r12]
        CMP     r2, #0
        MOVNE   r0, #ModHandReason_Free
        SWINE   XOS_Module
        MOV     r2, #0
        STR     r2, [r12]
        SETV
        EXIT
Ben Avison's avatar
Ben Avison committed
229 230 231 232

MyByteV ROUT
        TEQ     r0, #OsByte_WriteCMOS
        MOVNE   pc, lr      ; only interested in when the CMOS is written
233
        ADR     r0, %F10
Ben Avison's avatar
Ben Avison committed
234 235 236
        Push    "r0, r12"   ; set up address for claimant to return to (NB this code is not 26-bit compatible)
        MOV     r0, #OsByte_WriteCMOS
        MOV     pc, lr      ; pass on, and...
237
10                          ; ... we end up here after the CMOS has been written
Ben Avison's avatar
Ben Avison committed
238 239
        Pull    "r12"       ; get our own r12 back
        Pull    "pc", VS    ; if an error, just pass it up to original claim address
240
      [ StoreInHAL
241
        Push    "r0-r7"
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
        SUB     sp, sp, #4  ; allocate space on stack for buffer

        MOV     r7, r1
        MOV     r0, #&CF    ; open existing file for read/write, error if missing or directory, no path
        LDR     r1, [r12]
        SWI     XOS_Find
        BVS     %F90
        MOV     r1, r0

        ; Search for the CMOS in the ROM on disc - can't be sure it matches the
        ; running version!
        LDR     r5, CMOSMarker
        LDR     r6, OSIm
        MOV     r0, #4      ; read bytes from current file pointer
20      MOV     r2, sp
        MOV     r3, #4
        SWI     XOS_GBPB
        BVS     %F80
        LDR     r14, [sp]
        TEQ     r14, r6
        BEQ     %F80        ; got to the end of the HAL and not found CMOS - give up
        TEQ     r14, r5
        BNE     %B20

        ; Read size of block in HAL
        MOV     r2, sp
        MOV     r3, #4
        SWI     XOS_GBPB
        BVS     %F80
        LDR     r6, [sp]
        MOV     r5, r1      ; keep file handle safe

        ; Copy the CMOS RAM into a block on the stack (should be small enough)
        ; in physical address order
        SUB     sp, sp, r6
        MOV     r3, #0
30      MOV     r0, #OsByte_ReadCMOS
        MOV     r1, r3
        CMP     r3, #&10
        ADDLO   r1, r1, #&40
        CMP     r3, #&40
        ADDLO   r1, r1, #&F0
        CMP     r3, #&100
        SUBLO   r1, r1, #&40
        SWI     XOS_Byte
        MOVVS   r2, #0
        STRB    r2, [sp, r3]
        ADD     r3, r3, #1
        CMP     r3, r6
        BLO     %B30

        ; Overwrite the HAL with the block from the stack
        MOV     r0, #2      ; write bytes at current file pointer
        MOV     r1, r5
        MOV     r2, sp
        MOV     r3, r6
        SWI     XOS_GBPB
        ADD     sp, sp, r6

80      MOV     r2, r0
        MRS     r3, CPSR
        MOV     r0, #0      ; close file
        SWI     XOS_Find
        MOV     r0, r2
        MSR     CPSR_f, r3
90      ADD     sp, sp, #4  ; skip data block
        STRVS   r0, [sp]
309
        Pull    "r0-r7, pc"  ; go to original claim address
310
      |
Ben Avison's avatar
Ben Avison committed
311 312 313 314 315
        Push    "r0"
        LDR     r0, [r12]
        SWI     XOS_CLI     ; save the CMOS to the file
        STRVS   r0, [sp]
        Pull    "r0, pc"    ; go to original claim address
316
      ]
Ben Avison's avatar
Ben Avison committed
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331

Final   ROUT
        Entry
        ; It's good practice to remove our callback here just in case we got
        ; killed before it was triggered.
        ADR     r0, CallBackFromInit
        MOV     r1, r12
        SWI     XOS_RemoveCallBack

        ; Get off ByteV, if we were on it
        MOV     r0, #ByteV
        ADR     r1, MyByteV
        MOV     r2, r12
        SWI     XOS_Release

332
        ; The block pointed at by r12 is freed for us by the kernel if nonzero
Ben Avison's avatar
Ben Avison committed
333 334 335 336 337

        CLRV
        EXIT

        END