mirror of
https://github.com/BertoldVdb/ms-tools.git
synced 2025-12-10 07:44:46 +01:00
Initial attempt at adding some functions to MS213x firmware
This commit is contained in:
parent
9866c7b404
commit
162cc22d62
15 changed files with 391 additions and 0 deletions
5
ms213x_patch/asm/asm.sh
Executable file
5
ms213x_patch/asm/asm.sh
Executable file
|
|
@ -0,0 +1,5 @@
|
|||
as31 -Fbin init.asm
|
||||
as31 -Fbin hook.asm
|
||||
as31 -Fbin finishf660.asm
|
||||
as31 -Fbin finishsig.asm
|
||||
as31 -Fbin readinfo.asm
|
||||
36
ms213x_patch/asm/finishf660.asm
Normal file
36
ms213x_patch/asm/finishf660.asm
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
INC DPTR
|
||||
MOVX @DPTR, A
|
||||
|
||||
MOV DPTR, #0x7b10
|
||||
MOVX A, @DPTR
|
||||
MOV R7, A
|
||||
|
||||
INC DPTR
|
||||
MOVX A, @DPTR
|
||||
MOV R6, A
|
||||
|
||||
INC DPTR
|
||||
MOVX A, @DPTR
|
||||
MOV R5, A
|
||||
|
||||
INC DPTR
|
||||
MOVX A, @DPTR
|
||||
MOV R4, A
|
||||
|
||||
MOV DPTR, #0xf660
|
||||
MOV A, R7
|
||||
MOVX @DPTR, A
|
||||
|
||||
INC DPTR
|
||||
MOV A, R6
|
||||
MOVX @DPTR, A
|
||||
|
||||
INC DPTR
|
||||
MOV A, R5
|
||||
MOVX @DPTR, A
|
||||
|
||||
INC DPTR
|
||||
MOV A, R4
|
||||
MOVX @DPTR, A
|
||||
|
||||
RET
|
||||
1
ms213x_patch/asm/finishf660.bin
Normal file
1
ms213x_patch/asm/finishf660.bin
Normal file
|
|
@ -0,0 +1 @@
|
|||
Јрђ{аяЈаюЈаэЈаьђц`прЈорЈнрЈмр"
|
||||
7
ms213x_patch/asm/finishsig.asm
Normal file
7
ms213x_patch/asm/finishsig.asm
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
ORL A, R7
|
||||
|
||||
MOV DPTR, #0x7b14
|
||||
MOVX @DPTR, A
|
||||
|
||||
MOV R7, A
|
||||
RET
|
||||
1
ms213x_patch/asm/finishsig.bin
Normal file
1
ms213x_patch/asm/finishsig.bin
Normal file
|
|
@ -0,0 +1 @@
|
|||
O<EFBFBD>{đ˙"
|
||||
82
ms213x_patch/asm/hook.asm
Normal file
82
ms213x_patch/asm/hook.asm
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
hookRun:
|
||||
MOV DPTR, #0x12b3
|
||||
|
||||
MOVX A, @DPTR
|
||||
XRL A, R0
|
||||
JNZ hookRet
|
||||
|
||||
LCALL hookWork
|
||||
|
||||
MOV DPTR, #0x12b3+1
|
||||
MOVX @DPTR, A
|
||||
INC DPTR
|
||||
MOV A, R2
|
||||
MOVX @DPTR, A
|
||||
INC DPTR
|
||||
MOV A, R3
|
||||
MOVX @DPTR, A
|
||||
INC DPTR
|
||||
MOV A, R4
|
||||
MOVX @DPTR, A
|
||||
INC DPTR
|
||||
MOV A, R5
|
||||
MOVX @DPTR, A
|
||||
INC DPTR
|
||||
MOV A, R6
|
||||
MOVX @DPTR, A
|
||||
INC DPTR
|
||||
MOV A, R7
|
||||
MOVX @DPTR, A
|
||||
MOV DPTR, #0x12b3
|
||||
MOV A, #0xFF
|
||||
RLC A
|
||||
MOVX @DPTR, A
|
||||
|
||||
SETB EA
|
||||
|
||||
hookRet:
|
||||
RET
|
||||
|
||||
hookWork:
|
||||
CLR EA
|
||||
|
||||
MOV DPTR, #0x12b3+1
|
||||
MOVX A, @DPTR
|
||||
MOV 1, A
|
||||
|
||||
INC DPTR
|
||||
MOVX A, @DPTR
|
||||
MOV 0, A
|
||||
|
||||
PUSH 0
|
||||
PUSH 1
|
||||
|
||||
INC DPTR
|
||||
MOVX A, @DPTR
|
||||
MOV R3, A
|
||||
|
||||
INC DPTR
|
||||
MOVX A, @DPTR
|
||||
MOV R4, A
|
||||
|
||||
INC DPTR
|
||||
MOVX A, @DPTR
|
||||
MOV R5, A
|
||||
|
||||
INC DPTR
|
||||
MOVX A, @DPTR
|
||||
MOV R6, A
|
||||
|
||||
INC DPTR
|
||||
MOVX A, @DPTR
|
||||
MOV R7, A
|
||||
|
||||
RRC A
|
||||
MOV A, R7
|
||||
|
||||
MOV DPH, R3
|
||||
MOV DPL, R4
|
||||
|
||||
RET ;Call address in HID+1
|
||||
|
||||
|
||||
BIN
ms213x_patch/asm/hook.bin
Normal file
BIN
ms213x_patch/asm/hook.bin
Normal file
Binary file not shown.
18
ms213x_patch/asm/init.asm
Normal file
18
ms213x_patch/asm/init.asm
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
; Tell host about the existence of this patch
|
||||
|
||||
MOV DPTR, #0x7B00
|
||||
MOV A, #'B'
|
||||
MOVX @DPTR, A
|
||||
INC DPTR
|
||||
MOV A, #'V'
|
||||
MOVX @DPTR, A
|
||||
INC DPTR
|
||||
MOV A, #'D'
|
||||
MOVX @DPTR, A
|
||||
INC DPTR
|
||||
MOV A, #'B'
|
||||
MOVX @DPTR, A
|
||||
INC DPTR
|
||||
CLR A
|
||||
MOVX @DPTR, A
|
||||
RET
|
||||
BIN
ms213x_patch/asm/init.bin
Normal file
BIN
ms213x_patch/asm/init.bin
Normal file
Binary file not shown.
26
ms213x_patch/asm/readinfo.asm
Normal file
26
ms213x_patch/asm/readinfo.asm
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
; Resolution info
|
||||
MOV DPTR, #0x7b10
|
||||
MOVX A, @DPTR
|
||||
MOV R2, A
|
||||
|
||||
INC DPTR
|
||||
MOVX A, @DPTR
|
||||
MOV R3, A
|
||||
|
||||
INC DPTR
|
||||
MOVX A, @DPTR
|
||||
MOV R4, A
|
||||
|
||||
INC DPTR
|
||||
MOVX A, @DPTR
|
||||
MOV R5, A
|
||||
|
||||
; Signal info
|
||||
INC DPTR
|
||||
MOVX A, @DPTR
|
||||
|
||||
; Frame counter
|
||||
MOV R6, 0x29
|
||||
MOV R7, 0x28
|
||||
|
||||
RET
|
||||
1
ms213x_patch/asm/readinfo.bin
Normal file
1
ms213x_patch/asm/readinfo.bin
Normal file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD>{את£א<C2A3>£א<C2A3>£א£א®)¯("
|
||||
48
ms213x_patch/main.go
Normal file
48
ms213x_patch/main.go
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/BertoldVdb/ms-tools/mshal/ms213x"
|
||||
)
|
||||
|
||||
func main() {
|
||||
input := flag.String("input", "", "Input filename")
|
||||
output := flag.String("output", "/tmp/modified.bin", "Output filename")
|
||||
flag.Parse()
|
||||
|
||||
in, err := os.ReadFile(*input)
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to open file:", err)
|
||||
}
|
||||
|
||||
if err := ms213x.CheckImage(in); err != nil {
|
||||
log.Fatalln("Failed to parse image:", in)
|
||||
}
|
||||
|
||||
clen := binary.BigEndian.Uint16(in[2:])
|
||||
code := in[0x30:]
|
||||
code = code[:clen]
|
||||
|
||||
code, err = patch(code)
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to patch code:", err)
|
||||
}
|
||||
|
||||
out := make([]byte, 0x30, 0x30+len(code)+4)
|
||||
copy(out, in)
|
||||
binary.BigEndian.PutUint16(out[2:], uint16(len(code)))
|
||||
|
||||
out = append(out, code...)
|
||||
out = binary.BigEndian.AppendUint32(out, 0)
|
||||
ms213x.FixImage(out)
|
||||
|
||||
os.WriteFile("/tmp/modcode.bin", code, 0644)
|
||||
|
||||
if err := os.WriteFile(*output, out, 0644); err != nil {
|
||||
log.Fatalln("Failed to write output:", err)
|
||||
}
|
||||
}
|
||||
BIN
ms213x_patch/ms213x_patch
Executable file
BIN
ms213x_patch/ms213x_patch
Executable file
Binary file not shown.
122
ms213x_patch/patch.go
Normal file
122
ms213x_patch/patch.go
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
_ "embed"
|
||||
)
|
||||
|
||||
type patcher struct {
|
||||
image []byte
|
||||
|
||||
hookOffset uint16
|
||||
}
|
||||
|
||||
//go:embed asm/init.bin
|
||||
var patchInit []byte
|
||||
|
||||
//go:embed asm/hook.bin
|
||||
var patchHook []byte
|
||||
|
||||
//go:embed asm/finishf660.bin
|
||||
var patchFinishf660 []byte
|
||||
|
||||
//go:embed asm/finishsig.bin
|
||||
var patchFinishSig []byte
|
||||
|
||||
//go:embed asm/readinfo.bin
|
||||
var patchReadInfo []byte
|
||||
|
||||
func (p *patcher) addCode(code []byte) uint16 {
|
||||
offs := len(p.image)
|
||||
p.image = append(p.image, code...)
|
||||
return uint16(offs)
|
||||
}
|
||||
|
||||
func (p *patcher) detourCall(offset uint16, dest uint16) {
|
||||
a := p.image[offset]
|
||||
if a != 0x02 && a != 0x12 {
|
||||
panic("Not LJMP or LCALL")
|
||||
}
|
||||
|
||||
var code [6]byte
|
||||
code[0] = 0x12 /* LCALL */
|
||||
binary.BigEndian.PutUint16(code[1:], dest)
|
||||
|
||||
code[3] = 0x02 /* LJMP */
|
||||
copy(code[4:], p.image[offset+1:]) /* Copy original address */
|
||||
|
||||
binary.BigEndian.PutUint16(p.image[offset+1:], p.addCode(code[:]))
|
||||
}
|
||||
|
||||
func (p *patcher) createHook(cmd uint8) uint16 {
|
||||
return p.addCode([]byte{
|
||||
0x78, cmd,
|
||||
0x02, byte(p.hookOffset >> 8), byte(p.hookOffset),
|
||||
})
|
||||
}
|
||||
|
||||
func (p *patcher) replaceJump(offset, dest uint16) {
|
||||
p.image[offset] = 0x02
|
||||
binary.BigEndian.PutUint16(p.image[offset+1:], dest)
|
||||
}
|
||||
|
||||
func patch(in []byte) ([]byte, error) {
|
||||
/* Check if it is a file we know how to handle */
|
||||
hash := sha256.Sum256(in)
|
||||
hashStr := hex.EncodeToString(hash[:])
|
||||
if hashStr != "cc67f79a043da85dc8e6688a22111ade626e519e1ab549f110b3a06308190047" {
|
||||
return nil, fmt.Errorf("code hash %s is not supported", hashStr)
|
||||
}
|
||||
|
||||
p := patcher{
|
||||
image: in,
|
||||
}
|
||||
|
||||
/* Add init code */
|
||||
p.detourCall(0x4d48, p.addCode(patchInit))
|
||||
|
||||
/* Add hook code and update its internal jump */
|
||||
p.hookOffset = p.addCode(patchHook)
|
||||
binary.BigEndian.PutUint16(p.image[p.hookOffset+8:], binary.BigEndian.Uint16(p.image[p.hookOffset+8:])+p.hookOffset)
|
||||
|
||||
/* Add hook entry to main loop */
|
||||
p.detourCall(0x4d70, p.createHook(0xEF)) /* Not in IRQ, but handled the same as the other USB commands */
|
||||
|
||||
/* Add 0xEE, remove result codes 0xFF and 0xFE which are legitimate commands (function unclear, can still call them
|
||||
* via hook if needed) */
|
||||
table, dflt := p.jumptableParse(0x1d9c)
|
||||
var newTable []jumptableEntry
|
||||
needInsert := true
|
||||
for _, b := range table {
|
||||
if b.Key > 0xEE && needInsert {
|
||||
needInsert = false
|
||||
newTable = append(newTable, jumptableEntry{
|
||||
Key: 0xEE,
|
||||
Address: p.createHook(0xEE),
|
||||
})
|
||||
}
|
||||
if b.Key >= 0xFE {
|
||||
break
|
||||
}
|
||||
newTable = append(newTable, b)
|
||||
}
|
||||
p.jumptableWrite(0x1d9c, newTable, dflt)
|
||||
|
||||
/* Write 0xF660 also to safe place (0x7b10) */
|
||||
binary.BigEndian.PutUint16(p.image[0xbbb3:], 0x7b10)
|
||||
binary.BigEndian.PutUint16(p.image[0xbbbf:], 0x7b12)
|
||||
p.replaceJump(0xbbc3, p.addCode(patchFinishf660))
|
||||
|
||||
/* Write signal info to safe place (0x7b14) */
|
||||
p.replaceJump(0xe9c6, p.addCode(patchFinishSig))
|
||||
|
||||
/* Finally, add read results function */
|
||||
log.Printf("ReadInfo Offset: %02x", p.addCode(patchReadInfo))
|
||||
|
||||
return p.image, nil
|
||||
}
|
||||
44
ms213x_patch/patch_jumptable.go
Normal file
44
ms213x_patch/patch_jumptable.go
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
package main
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
type jumptableEntry struct {
|
||||
Key uint8
|
||||
Address uint16
|
||||
}
|
||||
|
||||
func (p *patcher) jumptableParse(offset uint16) ([]jumptableEntry, uint16) {
|
||||
var results []jumptableEntry
|
||||
|
||||
lastKey := -1
|
||||
for {
|
||||
addr := binary.BigEndian.Uint16(p.image[offset:])
|
||||
offset += 2
|
||||
if addr > 0 {
|
||||
key := int(p.image[offset])
|
||||
offset++
|
||||
|
||||
if key < lastKey {
|
||||
panic("Parse error")
|
||||
}
|
||||
lastKey = key
|
||||
|
||||
results = append(results, jumptableEntry{
|
||||
Key: uint8(key),
|
||||
Address: addr,
|
||||
})
|
||||
} else {
|
||||
return results, binary.BigEndian.Uint16(p.image[offset:])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *patcher) jumptableWrite(offset uint16, entries []jumptableEntry, dflt uint16) {
|
||||
for _, m := range entries {
|
||||
binary.BigEndian.PutUint16(p.image[offset:], m.Address)
|
||||
p.image[offset+2] = m.Key
|
||||
offset += 3
|
||||
}
|
||||
binary.BigEndian.PutUint16(p.image[offset:], 0)
|
||||
binary.BigEndian.PutUint16(p.image[offset+2:], dflt)
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue