diff --git a/cli/dumprom.go b/cli/dumprom.go index 09652e7..5b59219 100644 --- a/cli/dumprom.go +++ b/cli/dumprom.go @@ -3,7 +3,7 @@ package main import ( "bytes" "fmt" - "io/ioutil" + "os" "strings" "time" @@ -23,6 +23,7 @@ type dumpCodeParams struct { addrLoad int addrHook int valueHook byte + delay time.Duration } func (d *DumpROM) Run(c *Context) error { @@ -36,6 +37,14 @@ func (d *DumpROM) Run(c *Context) error { p.addrLoad = 0xC4A0 p.addrHook = 9 p.valueHook = 0x96 + } else if strings.Contains(devType, "MS2107") { + p.addrMailbox = 0xD000 + p.addrTemp = 0xD100 + p.addrTempLen = 256 + p.addrLoad = 0xC800 + p.addrHook = 8 + p.valueHook = 1 + p.delay = 25 * time.Millisecond } else if strings.Contains(devType, "MS2109") { p.addrMailbox = 0xCBF0 p.addrTemp = 0xD300 @@ -52,7 +61,7 @@ func (d *DumpROM) Run(c *Context) error { return err } - return ioutil.WriteFile(d.Filename, code, 0644) + return os.WriteFile(d.Filename, code, 0644) } //go:embed asm/dumprom.bin @@ -104,7 +113,7 @@ func (d *DumpROM) work(ms *mshal.HAL, p dumpCodeParams) ([]byte, error) { return nil, err } - /* Enable USB hook */ + /* Enable USB/Periodic hook */ if err := mshal.WriteByte(config, p.addrHook, p.valueHook); err != nil { return nil, err } @@ -133,6 +142,8 @@ func (d *DumpROM) work(ms *mshal.HAL, p dumpCodeParams) ([]byte, error) { return nil, err } + time.Sleep(p.delay) + ack, err := mshal.ReadByte(xdata, p.addrMailbox) if err != nil { return nil, err diff --git a/mshal/asm/asm.sh b/mshal/asm/asm.sh index 534c97c..f329c20 100755 --- a/mshal/asm/asm.sh +++ b/mshal/asm/asm.sh @@ -9,3 +9,4 @@ rm hook_2106.asm as31 -Fbin gpio.asm as31 -Fbin code.asm as31 -Fbin i2cRead2109.asm +as31 -Fbin i2cRead2107.asm diff --git a/mshal/asm/i2cRead2107.asm b/mshal/asm/i2cRead2107.asm new file mode 100644 index 0000000..c0429f6 --- /dev/null +++ b/mshal/asm/i2cRead2107.asm @@ -0,0 +1,2 @@ +MOV 0x23.5, C +LJMP 0x5934 diff --git a/mshal/asm/i2cRead2107.bin b/mshal/asm/i2cRead2107.bin new file mode 100644 index 0000000..286ccf9 --- /dev/null +++ b/mshal/asm/i2cRead2107.bin @@ -0,0 +1 @@ +’Y4 \ No newline at end of file diff --git a/mshal/hal.go b/mshal/hal.go index e28c8de..68abba1 100644 --- a/mshal/hal.go +++ b/mshal/hal.go @@ -62,9 +62,13 @@ func New(dev gohid.HIDDevice, config HALConfig) (*HAL, error) { case 0xa7: h.deviceType = 2109 + case 0xff: /* TODO: Find a better ID register, as this will likely match many devices */ + h.deviceType = 2107 + case 0x00: /* TODO: Find a better ID register, as this will likely match many devices */ h.deviceType = 2130 config.PatchTryInstall = false + default: return nil, ErrorUnknownDevice } @@ -140,6 +144,8 @@ func (h *HAL) GetDeviceType() string { return "MS2106" } else if h.deviceType == 2130 { return "MS2130" + } else if h.deviceType == 2107 { + return "MS2107" } return "MS2109" diff --git a/mshal/hal_patch_i2c.go b/mshal/hal_patch_i2c.go index 04f267e..e79ce13 100644 --- a/mshal/hal_patch_i2c.go +++ b/mshal/hal_patch_i2c.go @@ -2,7 +2,9 @@ package mshal func (h *HAL) patchI2CStart() error { addr := 0x3639 - if h.deviceType == 2109 { + if h.deviceType == 2107 { + addr = 0x68bd + } else if h.deviceType == 2109 { addr = 0x6a8c } @@ -12,7 +14,9 @@ func (h *HAL) patchI2CStart() error { func (h *HAL) patchI2CStop() error { addr := 0x3730 - if h.deviceType == 2109 { + if h.deviceType == 2107 { + addr = 0x6b5b + } else if h.deviceType == 2109 { addr = 0x6aba } _, err := h.PatchExecFunc(true, addr, PatchExecFuncRequest{}) @@ -21,7 +25,7 @@ func (h *HAL) patchI2CStop() error { func (h *HAL) patchI2CRead(ack bool) (uint8, error) { addr := 0x26cb - if h.deviceType == 2109 { + if h.deviceType == 2109 || h.deviceType == 2107 { addr = h.patchCallAddrs[3] } r7 := byte(1) @@ -34,11 +38,13 @@ func (h *HAL) patchI2CRead(ack bool) (uint8, error) { func (h *HAL) patchI2CWrite(value uint8) (bool, error) { addr := 0x2126 - if h.deviceType == 2109 { + if h.deviceType == 2107 { + addr = 0x5323 + } else if h.deviceType == 2109 { addr = 0x4648 } resp, err := h.PatchExecFunc(true, addr, PatchExecFuncRequest{R7_A: value}) - if h.deviceType == 2109 { + if h.deviceType != 2106 { return resp.C, err } return resp.R7 > 0, err diff --git a/mshal/hal_patch_install.go b/mshal/hal_patch_install.go index 6c8416a..bbf5d03 100644 --- a/mshal/hal_patch_install.go +++ b/mshal/hal_patch_install.go @@ -7,6 +7,7 @@ import ( "encoding/hex" "errors" "hash/crc32" + "time" ) func (h *HAL) patchAlloc(len int) int { @@ -71,9 +72,9 @@ func patchTrampolineEncode(orig []byte, origAddr int, R0Value byte, hookAddr int return result } -func (h *HAL) patchTrampolineInstall(ram MemoryRegion, replaceCode bool, addr int, R0value byte, hookAddr int) error { +func (h *HAL) patchTrampolineInstall(ram MemoryRegion, oldCode []byte, addr int, R0value byte, hookAddr int) error { var trampoline []byte - if replaceCode { + if len(oldCode) == 0 { replaceLen := 0 var in [14]byte @@ -93,7 +94,7 @@ func (h *HAL) patchTrampolineInstall(ram MemoryRegion, replaceCode bool, addr in trampoline = patchTrampolineEncode(in[:replaceLen], addr+replaceLen, R0value, hookAddr) } else { - trampoline = patchTrampolineEncode(nil, 0, R0value, hookAddr) + trampoline = patchTrampolineEncode(oldCode, 0, R0value, hookAddr) } trampolineAddr := h.patchAlloc(len(trampoline)) @@ -138,8 +139,11 @@ var codeGpio []byte //go:embed asm/code.bin var codeMOVC []byte +//go:embed asm/i2cRead2107.bin +var codei2cRead2107 []byte + //go:embed asm/i2cRead2109.bin -var codei2cRead []byte +var codei2cRead2109 []byte var installBlobs2106 = []CodeBlob{ { @@ -151,6 +155,18 @@ var installBlobs2106 = []CodeBlob{ Data: codeMOVC, }} +var installBlobs2107 = []CodeBlob{ + { + Data: codeCallgate2109, + Relocate: relocateCallgate, + }, { + Data: codeGpio, + }, { + Data: codeMOVC, + }, { + Data: codei2cRead2107, + }} + var installBlobs2109 = []CodeBlob{ { Data: codeCallgate2109, @@ -160,7 +176,7 @@ var installBlobs2109 = []CodeBlob{ }, { Data: codeMOVC, }, { - Data: codei2cRead, + Data: codei2cRead2109, }, } @@ -172,19 +188,28 @@ func (h *HAL) EEPROMReloadUser() error { ram := h.MemoryRegionGet(MemoryRegionRAM) userConfig := h.MemoryRegionGet(MemoryRegionUserConfig) - addr, _, err := h.patchHookGet(userConfig, true) + doInIRQ := true + var loadEEPROM []byte + if h.deviceType == 2106 { + loadEEPROM = []byte{0x02, 0x12, 0x82} + } else if h.deviceType == 2107 { + doInIRQ = false + loadEEPROM = []byte{0x02, 0x66, 0x56} + defer time.Sleep(125 * time.Millisecond) + } else if h.deviceType == 2109 { + loadEEPROM = []byte{0x02, 0x5f, 0x19} + } else { + return ErrorUnknownDevice + } + + /* Write RET and disable callback */ + addr, _, err := h.patchHookGet(userConfig, doInIRQ) if err != nil { return err - } - - /* Write RET and enable callback */ - if err := h.patchHookConfigure(userConfig, true, false); err != nil { + } else if err := h.patchHookSet(userConfig, doInIRQ, false); err != nil { + return err + } else if err := h.patchHookSet(userConfig, !doInIRQ, false); err != nil { return err - } - - loadEEPROM := []byte{0x02, 0x12, 0x82} - if h.deviceType == 2109 { - loadEEPROM = []byte{0x02, 0x5f, 0x19} } /* Reload EEPROM from IRQ context */ @@ -192,7 +217,7 @@ func (h *HAL) EEPROMReloadUser() error { return err } - return h.patchHookConfigure(userConfig, true, true) + return h.patchHookSet(userConfig, doInIRQ, true) } func (h *HAL) EEPROMIgnoreUser() error { @@ -205,6 +230,7 @@ func (h *HAL) EEPROMIgnoreUser() error { ff := bytes.Repeat([]byte{0xFF}, userConfig.GetLength()) ff[4] = 0 ff[5] = 0 + ff[8] = 0 _, err := userConfig.Access(true, 0, ff) return err @@ -222,14 +248,19 @@ func (h *HAL) EEPROMIsLoaded() (bool, int, error) { if h.deviceType == 2106 { return hdr[0] == 0x5a && hdr[1] == 0xa5, eepromLen, nil + } else if h.deviceType == 2107 { + if hdr[0] == 0x08 && hdr[1] == 0x16 { + return true, eepromLen, nil + } + return hdr[0] == 0x32 && hdr[1] == 0x64, eepromLen, nil + } else if h.deviceType == 2109 { + if hdr[0] == 0xa5 && hdr[1] == 0x5a { + return true, eepromLen, nil + } + return hdr[0] == 0x96 && hdr[1] == 0x69, eepromLen, nil } - if hdr[0] == 0xa5 && hdr[1] == 0x5a { - return true, eepromLen, nil - } - - /* 2109 can also use 16bit eeproms and they have a different header */ - return hdr[0] == 0x96 && hdr[1] == 0x69, eepromLen, nil + return false, 0, ErrorUnknownDevice } func (h *HAL) patchHookGet(loc MemoryRegion, inIRQ bool) (int, bool, error) { @@ -241,20 +272,25 @@ func (h *HAL) patchHookGet(loc MemoryRegion, inIRQ bool) (int, bool, error) { value, err := ReadByte(loc, 0x5) return 0xc420, value == 0x5a, err } + } else if h.deviceType == 2107 { + value, err := ReadByte(loc, 0x8) + if inIRQ { + return 0xc810, value&2 > 0, err + } else { + return 0xc800, value&1 > 0, err + } + } else if h.deviceType == 2109 { + value, err := ReadByte(loc, 0x4) + if inIRQ { + return 0xcc20, value&4 > 0, err + } else { + return 0xcc00, value&1 > 0, err + } } - value, err := ReadByte(loc, 0x4) - if err != nil { - return 0, false, err - } - - if inIRQ { - return 0xcc20, value&4 > 0, nil - } - - return 0xcc00, value&1 > 0, nil + return 0, false, ErrorUnknownDevice } -func (h *HAL) patchHookConfigure(loc MemoryRegion, inIRQ bool, enable bool) error { +func (h *HAL) patchHookSet(loc MemoryRegion, inIRQ bool, enable bool) error { if h.config.LogFunc != nil { h.config.LogFunc(2, "Configuring userhook: inIRQ=%v, enable=%v", inIRQ, enable) } @@ -272,26 +308,47 @@ func (h *HAL) patchHookConfigure(loc MemoryRegion, inIRQ bool, enable bool) erro } return WriteByte(loc, 0x5, value) } - } - - value, err := ReadByte(loc, 0x4) - if err != nil { - return err - } - - if inIRQ { - value &= ^byte(4) - if enable { - value |= 4 + } else if h.deviceType == 2107 { + value, err := ReadByte(loc, 0x8) + if err != nil { + return err } - } else { - value &= ^byte(1) - if enable { - value |= 1 + + if inIRQ { + value &= ^byte(2) + if enable { + value |= 2 + } + } else { + value &= ^byte(1) + if enable { + value |= 1 + } } + + return WriteByte(loc, 0x8, value) + } else if h.deviceType == 2109 { + value, err := ReadByte(loc, 0x4) + if err != nil { + return err + } + + if inIRQ { + value &= ^byte(4) + if enable { + value |= 4 + } + } else { + value &= ^byte(1) + if enable { + value |= 1 + } + } + + return WriteByte(loc, 0x4, value) } - return WriteByte(loc, 0x4, value) + return ErrorUnknownDevice } func (h *HAL) patchInitAlloc(userConfig MemoryRegion) (bool, error) { @@ -313,6 +370,8 @@ func (h *HAL) patchInstall() (bool, error) { var installBlobs []CodeBlob if h.deviceType == 2109 { installBlobs = installBlobs2109 + } else if h.deviceType == 2107 { + installBlobs = installBlobs2107 } else if h.deviceType == 2106 { installBlobs = installBlobs2106 } else { @@ -416,27 +475,41 @@ func (h *HAL) patchInstall() (bool, error) { return true, err } - if userCodePresent && (!enableIrq || !enableNorm) { - return true, ErrorPatchFailed + var oldCodeIRQ []byte + if userCodePresent { + if !enableIrq || !enableNorm { + return true, ErrorPatchFailed + } + } else { + enableIrq = true + enableNorm = true + if h.deviceType == 2107 { + /* If the USB IRQ patch is enabled it must call the original handler (or do everything itself) */ + oldCodeIRQ = []byte{0x02, 0x54, 0xae} + } + } + + if h.deviceType == 2107 { + /* Disable callbacks during writing, just putting RET is not enough */ + if err := h.patchHookSet(userConfig, true, false); err != nil { + return true, err + } else if err := h.patchHookSet(userConfig, false, false); err != nil { + return true, err + } } /* Install trampolines to callgate */ - if err := h.patchTrampolineInstall(ram, userCodePresent, addrIrq, 0xee, h.patchCallAddrs[0]); err != nil { + if err := h.patchTrampolineInstall(ram, oldCodeIRQ, addrIrq, 0xee, h.patchCallAddrs[0]); err != nil { + return true, err + } else if err := h.patchTrampolineInstall(ram, nil, addrNorm, 0xef, h.patchCallAddrs[0]); err != nil { return true, err } - if err := h.patchTrampolineInstall(ram, userCodePresent, addrNorm, 0xef, h.patchCallAddrs[0]); err != nil { + /* Re-enable callbacks */ + if err := h.patchHookSet(userConfig, true, enableIrq); err != nil { + return true, err + } else if err := h.patchHookSet(userConfig, false, enableNorm); err != nil { return true, err - } - - /* Enable callbacks */ - if !userCodePresent { - if err := h.patchHookConfigure(userConfig, true, true); err != nil { - return true, err - } - if err := h.patchHookConfigure(userConfig, false, true); err != nil { - return true, err - } } /* Write patch sumblock */ diff --git a/mshal/hal_region.go b/mshal/hal_region.go index b274555..08d519f 100644 --- a/mshal/hal_region.go +++ b/mshal/hal_region.go @@ -79,7 +79,7 @@ func (h *HAL) MemoryRegionList() []MemoryRegionNameType { MemoryRegionUserConfig, } - if h.deviceType == 2106 || h.deviceType == 2109 { + if h.deviceType == 2106 || h.deviceType == 2109 || h.deviceType == 2107 { list = append(list, MemoryRegionUserRAM) } @@ -145,6 +145,16 @@ func (h *HAL) MemoryRegionGet(name MemoryRegionNameType) MemoryRegion { } } + if h.deviceType == 2107 { + switch t { + case MemoryRegionUserRAM: + return regionWrapPartial(MemoryRegionUserRAM, h.MemoryRegionGet(MemoryRegionRAM), 0xC000, 0x1400) + + case MemoryRegionUserConfig: + return regionWrapPartial(MemoryRegionUserConfig, h.MemoryRegionGet(MemoryRegionUserRAM), 0x7D0, 0x30) + } + } + if h.deviceType == 2109 { switch t { case MemoryRegionUserRAM: