sdcmos 12.7 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
        GET     ListOpts
        GET     Macros
        GET     System
        GET     Proc
        GET     HighFSI
        GET     ModHand
        GET     OsBytes
38 39 40 41 42
        GET     OsWords
        GET     CMOS
        GET     FSNumbers
        GET     NewErrors
        GET     Territory
Ben Avison's avatar
Ben Avison committed
43
        GET     FileTypes
44
        GET     Services
Ben Avison's avatar
Ben Avison committed
45 46 47 48 49 50 51 52 53
        GET     VersionASM

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

        ENTRY

        DCD     0 ; Start
        DCD     Init - |Asm$$Code|
        DCD     Final - |Asm$$Code|
54 55 56 57 58
      [ StoreInHAL
        DCD     Services - |Asm$$Code|
      |
        DCD     0 ; Service call handler
      ]
Ben Avison's avatar
Ben Avison committed
59 60 61 62 63 64 65 66 67 68 69 70 71
        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
72
Flags   DCD     ModuleFlag_32bit
Ben Avison's avatar
Ben Avison committed
73

74 75 76 77 78 79 80 81 82 83 84
 [ StoreInHAL

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

CMOSMarker UND  #&C305
OSIm    =       "OSIm"

 |

Ben Avison's avatar
Ben Avison committed
85 86
NonCanonicalisedPath
        =       "SDFS::0.$.CMOS", 0
87 88
NonCanonicalisedPath2
        =       "SDFS::0.$.!Boot.Loader.CMOS", 0
Ben Avison's avatar
Ben Avison committed
89 90 91 92 93 94 95
        ALIGN

SaveCMOS
        =       "SaveCMOS "
Len_SaveCMOS * .-SaveCMOS
        ALIGN

96 97
 ]

Ben Avison's avatar
Ben Avison committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
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.

119 120 121 122 123 124 125 126 127
        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
      ]
128
        BVS     %FT90
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 155 156 157 158 159 160 161 162 163 164

        ; 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
165 166 167 168 169 170 171 172 173
        ; 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

174 175 176 177
      [ StoreInHAL
        ; Allocate a buffer to hold filename of the ROM image plus terminator
        RSB     r3, r5, #1
      |
Ben Avison's avatar
Ben Avison committed
178 179 180
        ; 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
181 182
      ]
        MOV     r0, #ModHandReason_Claim
Ben Avison's avatar
Ben Avison committed
183 184 185 186 187
        SWI     XOS_Module
        BVS     %F90
        STR     r2, [r12]

        ; Get the canonicalised name
188
      [ :LNOT: StoreInHAL
Ben Avison's avatar
Ben Avison committed
189
        ADD     r2, r2, #Len_SaveCMOS
190
      ]
Ben Avison's avatar
Ben Avison committed
191 192 193 194 195 196
        MOV     r5, r3
        MOV     r0, #FSControl_CanonicalisePath
        MOV     r3, #0
        SWI     XOS_FSControl
        BVS     %F90

197
      [ :LNOT: StoreInHAL
Ben Avison's avatar
Ben Avison committed
198 199 200 201 202 203 204 205
        ; 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
206
      ]
Ben Avison's avatar
Ben Avison committed
207

208
        ; Check it's a file (or image file)
Ben Avison's avatar
Ben Avison committed
209 210 211 212 213 214
        MOV     r0, #OSFile_ReadWithTypeNoPath
        MOV     r1, r2
        SWI     XOS_File
        BVS     %F90
        TST     r0, #object_file
        BEQ     %F90
215 216 217

      [ :LNOT: StoreInHAL
        ; Check it's a sensible filetype
Ben Avison's avatar
Ben Avison committed
218 219
        LDR     r0, =FileType_Configuration
        TEQ     r6, r0
220 221
        LDRNE   r0, =FileType_MSDOS
        TEQNE   r6, r0
Ben Avison's avatar
Ben Avison committed
222
        BNE     %F90
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 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
      |
        ; If the time is in 1970 then the kernel didn't find a real time
        ; clock, and NetTime hasn't picked up a link yet
        SUB     sp, sp, #8
        MOV     r0, #OsWord_ReadRealTimeClock
        MOV     r1, #3      ; time as UTC 5 byte cs
        STRB    r1, [sp]
        MOV     r1, sp
        SWI     XOS_Word
        ADDVS   sp, sp, #8
        BVS     %F80

        LDR     r3, =((71 * 365) + 18) * 86400
        MOV     r0, #100    ; want cs to end of 1970 from epoch 1900
        UMULL   r3, r4, r0, r3
        LDR     r0, [sp, #0]
        LDRB    r1, [sp, #4]
        SUBS    r14, r0, r3
        SBCS    r14, r1, r4
        ADDPL   sp, sp, #8  ; now > 1970
        BPL     %F80

        ; Try and find the last saved value
        MOV     r0, #open_read :OR: open_mustopen :OR: open_nodir :OR: open_nopath
        LDR     r1, [r12]
        SWI     XOS_Find
        BVS     %F70
        MOV     r1, r0

        ; Search for the CMOS in the ROM on disc
        LDR     r5, CMOSMarker
        LDR     r6, OSIm
        MOV     r0, #OSGBPB_ReadFromPTR
50      MOV     r2, sp
        MOV     r3, #4
        SWI     XOS_GBPB
        BVS     %F60
        LDR     r14, [sp]
        TEQ     r14, r6
        BEQ     %F60        ; got to the end of the HAL and not found CMOS - give up
        TEQ     r14, r5
        BNE     %B50

        ; Read size of block in HAL
        MOV     r2, sp
        MOV     r3, #4
        SWI     XOS_GBPB
        BVS     %F60
        LDR     r6, [sp]

        ; Read the last timestamp
        MOV     r0, #OSGBPB_ReadFromGiven
        MOV     r2, sp
        MOV     r3, #5
        ADD     r4, r4, r6
        SWI     XOS_GBPB
        BVS     %F60

        ; Check it's not unset
        LDR     r3, [sp, #0]
        LDRB    r4, [sp, #4]
        ORRS    r3, r4, r3
        MOVNE   r0, sp
286 287
        SWINE   XTerritory_SetTime
        CLRV
288 289 290 291 292 293 294 295 296
60
        MRS     r3, CPSR    ; preserve V set ness
        MOV     r0, #0      ; close file
        SWI     XOS_Find
        MSR     CPSR_f, r3
70
        ADD     sp, sp, #8  ; skip temp block
        BVS     %F90
80
297
      ]
298 299 300
        ; All good
        CLRV
        EXIT
Ben Avison's avatar
Ben Avison committed
301

302 303 304 305 306 307 308 309 310 311 312
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
313

314 315 316 317 318 319 320 321 322 323 324 325
      [ StoreInHAL
Services ROUT
        TEQ     r1, #Service_ShutDown
        MOVNE   pc, lr
        Push    "r0, lr"    ; keep original r0 in case MyByteV returns an error
        Push    "pc"
        BL      %FT15       ; now write the values out, along with the timestamp
        NOP
        Pull    "r0, pc"    ; and on with the shutdown (don't claim)
      ]

MyByteV
Ben Avison's avatar
Ben Avison committed
326 327
        TEQ     r0, #OsByte_WriteCMOS
        MOVNE   pc, lr      ; only interested in when the CMOS is written
328
        ADR     r0, %F10
Ben Avison's avatar
Ben Avison committed
329 330 331
        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...
332
10                          ; ... we end up here after the CMOS has been written
Ben Avison's avatar
Ben Avison committed
333 334
        Pull    "r12"       ; get our own r12 back
        Pull    "pc", VS    ; if an error, just pass it up to original claim address
335
      [ StoreInHAL
336
15
337
        Push    "r0-r7"
338 339 340
        SUB     sp, sp, #4  ; allocate space on stack for buffer

        MOV     r7, r1
341
        MOV     r0, #open_update :OR: open_mustopen :OR: open_nodir :OR: open_nopath
342 343 344 345 346 347 348 349 350
        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
351
        MOV     r0, #OSGBPB_ReadFromPTR
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
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
390
        MOV     r0, #OSGBPB_WriteAtPTR
391 392 393 394
        MOV     r1, r5
        MOV     r2, sp
        MOV     r3, r6
        SWI     XOS_GBPB
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
        BVS     %F75

        ; Refresh the timestamp
        MOV     r0, #OsWord_ReadRealTimeClock
        MOV     r1, #3      ; time as UTC 5 byte cs
        STRB    r1, [sp]
        MOV     r1, sp
        SWI     XOS_Word

        MOVVC   r0, #OSGBPB_WriteAtPTR
        MOVVC   r1, r5
        MOVVC   r2, sp
        MOVVC   r3, #5
        SWIVC   XOS_GBPB
75
410 411
        ADD     sp, sp, r6

412
80      MOV     r2, r0      ; preserve the original error
413 414 415 416 417
        MRS     r3, CPSR
        MOV     r0, #0      ; close file
        SWI     XOS_Find
        MOV     r0, r2
        MSR     CPSR_f, r3
418
90      ADD     sp, sp, #4  ; skip temp block
419
        STRVS   r0, [sp]
420
        Pull    "r0-r7, pc" ; go to original claim address
421
      |
Ben Avison's avatar
Ben Avison committed
422 423 424 425 426
        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
427
      ]
Ben Avison's avatar
Ben Avison committed
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442

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

443
        ; The block pointed at by r12 is freed for us by the kernel if nonzero
Ben Avison's avatar
Ben Avison committed
444 445 446 447 448

        CLRV
        EXIT

        END