π
<-

HP Prime G2/D rentrée 2018 : spécifications astronomiques !

Re: HP Prime G2/D rentrée 2018 : spécifications astronomique

Unread postby Lionel Debroux » 18 Aug 2018, 07:39

Thanks Tim, it's heartening to read such information :)
Yeah, an ARMv7 chip usually has built-in security features in the core ISA, and then, the SoC maker can add a bit of silicon to expand on the security feature set.

I started writing the Go program for parsing HPPrimeOS.img I mentioned on MoHPC, but don't expect fast progress...
Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
User avatar
Lionel DebrouxSuper Modo
Niveau 14: CI (Calculateur de l'Infini)
Niveau 14: CI (Calculateur de l'Infini)
Level up: 11.3%
 
Posts: 6865
Joined: 23 Dec 2009, 00:00
Location: France
Gender: Male
Calculator(s):
MyCalcs profile
Class: -
GitHub: debrouxl

Re: HP Prime G2/D rentrée 2018 : spécifications astronomique

Unread postby critor » 18 Aug 2018, 09:06

Thanks, it's reliving. :)
So the checksum in files.sig has to be documented then.

So far, people who can are usually slightly older and don't dick around with exam mode, because they just don't need to. See the NumWorks who has the easiest to dick around with exam mode, since you can change anything in the source and rebuild it. As far as I know, nobody did.
Image
User avatar
critorAdmin
Niveau 19: CU (Créateur Universel)
Niveau 19: CU (Créateur Universel)
Level up: 47.5%
 
Posts: 41980
Images: 15737
Joined: 25 Oct 2008, 00:00
Location: Montpellier
Gender: Male
Calculator(s):
MyCalcs profile
YouTube: critor3000
Twitter: critor2000
GitHub: critor

Re: HP Prime G2/D rentrée 2018 : spécifications astronomique

Unread postby Lionel Debroux » 19 Aug 2018, 21:43

Current state of my HPPrime_OS.img Go parser:
Code: Select all
package main

import (
   "encoding/binary"
   "fmt"
   "io"
   "os"
)

func printOutputMessage(msg string) {
   io.WriteString(os.Stdout, msg)
}

func printErrorMessage(msg string) {
   io.WriteString(os.Stderr, msg)
}

func usage() {
   printErrorMessage("Usage: imgdump <input file>\n")
   os.Exit(1)
}

func exit(msg string) {
   printErrorMessage(msg)
   os.Exit(1)
}

func readNBytes(infile *os.File, count uint32) []byte {
   var bytes = make([]byte, count)
   nRead, err := io.ReadAtLeast(infile, bytes, len(bytes))
   if uint32(nRead) < count || err != nil {
      exit(err.Error())
   }
   return bytes
}

func main() {
   // The usual usage information if the program wasn't properly invoked...
   if len(os.Args) < 2 {
      usage()
   }
   infile, err := os.Open(os.Args[1])
   if err != nil {
      printErrorMessage(err.Error())
      printErrorMessage("\n")
      usage()
   }
   defer infile.Close()

   // Check real file size against embedded file size
   fileInfo, err := infile.Stat()
   if err != nil {
      exit(err.Error())
   }
   var realFileSize = fileInfo.Size()

   var embeddedFileSizeBytes = readNBytes(infile, 4)
   var embeddedFileSize = /*encoding.*/ binary.LittleEndian.Uint32(embeddedFileSizeBytes)
   if realFileSize != int64(embeddedFileSize) {
      exit("Embedded file size does not match file size\n")
   } else {
      fmt.Printf("File size is %d (0x%X) bytes\n", embeddedFileSize, embeddedFileSize)
   }

   // Now let's loop on the blocks, all of which seem to contain at least 20 bytes.
   var offset uint32 = 4
   var blockID uint32 = 1
   for offset < embeddedFileSize {
      var remainingBytes = embeddedFileSize - offset
      if remainingBytes < 16 {
         exit("Unhandled case 1")
      }
      fmt.Printf("Block #%d at offset %d (0x%X):\n", blockID, offset, offset)

      // Read, parse and display header.
      var blockHeader = readNBytes(infile, 12)
      var blockSize = /*encoding.*/ binary.LittleEndian.Uint32(blockHeader[0:4])
      if blockSize < 20 || blockSize > remainingBytes {
         exit(fmt.Sprintf("Invalid block size %d for block #%d", blockSize, blockID))
      }
      var dataSize = /*encoding.*/ binary.LittleEndian.Uint32(blockHeader[4:8])
      if dataSize > blockSize || dataSize > remainingBytes {
         exit(fmt.Sprintf("Invalid data size for block #%d", blockID))
      }
      var nameSize = /*encoding.*/ binary.LittleEndian.Uint32(blockHeader[8:12])
      if nameSize < 4 || nameSize > blockSize || nameSize > remainingBytes-8 {
         exit(fmt.Sprintf("Invalid name size for block #%d", blockID))
      }
      var name = readNBytes(infile, nameSize)
      var unknown = readNBytes(infile, 4)
      fmt.Printf("\tBlock size %d (0x%X), data size %d (0x%X), header size %d (0x%X)\n", blockSize, blockSize, dataSize, dataSize, nameSize, nameSize)
      fmt.Printf("\tName: '%s'\n", name)
      if unknown[0] != 0 || unknown[1] != 0 || unknown[2] != 0 || unknown[3] != 0 {
         exit("Unknown data is nonzero")
      }

      // Read data (TODO and deal with it).
      var data = readNBytes(infile, blockSize-16-nameSize)
      if data[0] == 0 {
         // Will store and use it later.
      }

      // Next block.
      offset += blockSize
      blockID++
   }
}


which outputs the following information for the 20180706 G2 firmware:
Code: Select all
File size is 17149860 (0x105AFA4) bytes
Block #1 at offset 4 (0x4):
        Block size 7602476 (0x74012C), data size 7602471 (0x740127), header size 4 (0x4)
        Name: ''
Block #2 at offset 7602480 (0x740130):
        Block size 354200 (0x56798), data size 354194 (0x56792), header size 4 (0x4)
        Name: ''
Block #3 at offset 7956680 (0x7968C8):
        Block size 4160 (0x1040), data size 4153 (0x1039), header size 12 (0xC)
        Name: 'files.sig'
Block #4 at offset 7960840 (0x797908):
        Block size 26324 (0x66D4), data size 26317 (0x66CD), header size 12 (0xC)
        Name: 'Bridge.jpg'
Block #5 at offset 7987164 (0x79DFDC):
        Block size 23840 (0x5D20), data size 23834 (0x5D1A), header size 12 (0xC)
        Name: 'Coins.jpg'
Block #6 at offset 8011004 (0x7A3CFC):
        Block size 612 (0x264), data size 607 (0x25F), header size 16 (0x10)
        Name: 'Custom_App.prgm'
Block #7 at offset 8011616 (0x7A3F60):
        Block size 752 (0x2F0), data size 747 (0x2EB), header size 24 (0x18)
        Name: 'dark_grad.hpthemepng'
Block #8 at offset 8012368 (0x7A4250):
        Block size 764 (0x2FC), data size 760 (0x2F8), header size 24 (0x18)
        Name: 'dark_menu.hpthemepng'
Block #9 at offset 8013132 (0x7A454C):
        Block size 1104 (0x450), data size 1100 (0x44C), header size 16 (0x10)
        Name: 'Demo_ARC.prgm'
Block #10 at offset 8014236 (0x7A499C):
        Block size 1136 (0x470), data size 1131 (0x46B), header size 16 (0x10)
        Name: 'Demo_ARC_P.prgm'
Block #11 at offset 8015372 (0x7A4E0C):
        Block size 1248 (0x4E0), data size 1242 (0x4DA), header size 16 (0x10)
        Name: 'Demo_BLIT.prgm'
Block #12 at offset 8016620 (0x7A52EC):
        Block size 1296 (0x510), data size 1291 (0x50B), header size 20 (0x14)
        Name: 'Demo_BLIT_P.prgm'
Block #13 at offset 8017916 (0x7A57FC):
        Block size 192 (0xC0), data size 188 (0xBC), header size 16 (0x10)
        Name: 'Demo_BREAK.prgm'
Block #14 at offset 8018108 (0x7A58BC):
        Block size 580 (0x244), data size 573 (0x23D), header size 16 (0x10)
        Name: 'Demo_CASE.prgm'
Block #15 at offset 8018688 (0x7A5B00):
        Block size 316 (0x13C), data size 311 (0x137), header size 20 (0x14)
        Name: 'Demo_CONTINUE.prgm'
Block #16 at offset 8019004 (0x7A5C3C):
        Block size 1244 (0x4DC), data size 1238 (0x4D6), header size 20 (0x14)
        Name: 'Demo_DIMGROB.prgm'
Block #17 at offset 8020248 (0x7A6118):
        Block size 1240 (0x4D8), data size 1234 (0x4D2), header size 20 (0x14)
        Name: 'Demo_DIMGROB_P.prgm'
Block #18 at offset 8021488 (0x7A65F0):
        Block size 216 (0xD8), data size 211 (0xD3), header size 20 (0x14)
        Name: 'Demo_Export.prgm'
Block #19 at offset 8021704 (0x7A66C8):
        Block size 784 (0x310), data size 777 (0x309), header size 20 (0x14)
        Name: 'Demo_FILLPOLY.prgm'
Block #20 at offset 8022488 (0x7A69D8):
        Block size 796 (0x31C), data size 791 (0x317), header size 24 (0x18)
        Name: 'Demo_FILLPOLY_P.prgm'
Block #21 at offset 8023284 (0x7A6CF4):
        Block size 184 (0xB8), data size 179 (0xB3), header size 16 (0x10)
        Name: 'Demo_FOR.prgm'
Block #22 at offset 8023468 (0x7A6DAC):
        Block size 2160 (0x870), data size 2156 (0x86C), header size 20 (0x14)
        Name: 'Demo_GETPIX.prgm'
Block #23 at offset 8025628 (0x7A761C):
        Block size 2172 (0x87C), data size 2167 (0x877), header size 20 (0x14)
        Name: 'Demo_GETPIX_P.prgm'
Block #24 at offset 8027800 (0x7A7E98):
        Block size 216 (0xD8), data size 211 (0xD3), header size 20 (0x14)
        Name: 'Demo_GETSIDES.prgm'
Block #25 at offset 8028016 (0x7A7F70):
        Block size 164 (0xA4), data size 159 (0x9F), header size 16 (0x10)
        Name: 'Demo_IF.prgm'
Block #26 at offset 8028180 (0x7A8014):
        Block size 160 (0xA0), data size 155 (0x9B), header size 16 (0x10)
        Name: 'Demo_IFERR.prgm'
Block #27 at offset 8028340 (0x7A80B4):
        Block size 1252 (0x4E4), data size 1246 (0x4DE), header size 20 (0x14)
        Name: 'Demo_INVERT.prgm'
Block #28 at offset 8029592 (0x7A8598):
        Block size 1208 (0x4B8), data size 1203 (0x4B3), header size 20 (0x14)
        Name: 'Demo_INVERT_P.prgm'
Block #29 at offset 8030800 (0x7A8A50):
        Block size 228 (0xE4), data size 224 (0xE0), header size 16 (0x10)
        Name: 'Demo_KILL.prgm'
Block #30 at offset 8031028 (0x7A8B34):
        Block size 688 (0x2B0), data size 682 (0x2AA), header size 16 (0x10)
        Name: 'Demo_LINE.prgm'
Block #31 at offset 8031716 (0x7A8DE4):
        Block size 700 (0x2BC), data size 694 (0x2B6), header size 20 (0x14)
        Name: 'Demo_LINE_P.prgm'
Block #32 at offset 8032416 (0x7A90A0):
        Block size 152 (0x98), data size 146 (0x92), header size 16 (0x10)
        Name: 'Demo_LOCAL.prgm'
Block #33 at offset 8032568 (0x7A9138):
        Block size 396 (0x18C), data size 389 (0x185), header size 20 (0x14)
        Name: 'Demo_PISERIES.prgm'
Block #34 at offset 8032964 (0x7A92C4):
        Block size 404 (0x194), data size 399 (0x18F), header size 24 (0x18)
        Name: 'Demo_PISERIES_P.prgm'
Block #35 at offset 8033368 (0x7A9458):
        Block size 1520 (0x5F0), data size 1515 (0x5EB), header size 16 (0x10)
        Name: 'Demo_RECT.prgm'
Block #36 at offset 8034888 (0x7A9A48):
        Block size 1536 (0x600), data size 1530 (0x5FA), header size 20 (0x14)
        Name: 'Demo_RECT_P.prgm'
Block #37 at offset 8036424 (0x7AA048):
        Block size 168 (0xA8), data size 164 (0xA4), header size 20 (0x14)
        Name: 'Demo_REPEAT.prgm'
Block #38 at offset 8036592 (0x7AA0F0):
        Block size 192 (0xC0), data size 187 (0xBB), header size 20 (0x14)
        Name: 'Demo_RETURN.prgm'
Block #39 at offset 8036784 (0x7AA1B0):
        Block size 1824 (0x720), data size 1820 (0x71C), header size 20 (0x14)
        Name: 'Demo_ROTATE.prgm'
Block #40 at offset 8038608 (0x7AA8D0):
        Block size 864 (0x360), data size 859 (0x35B), header size 20 (0x14)
        Name: 'Demo_SUBGROB.prgm'
Block #41 at offset 8039472 (0x7AAC30):
        Block size 464 (0x1D0), data size 458 (0x1CA), header size 20 (0x14)
        Name: 'Demo_SUBGROB_P.prgm'
Block #42 at offset 8039936 (0x7AAE00):
        Block size 2480 (0x9B0), data size 2475 (0x9AB), header size 24 (0x18)
        Name: 'Demo_Tetrahedron.prgm'
Block #43 at offset 8042416 (0x7AB7B0):
        Block size 2184 (0x888), data size 2180 (0x884), header size 24 (0x18)
        Name: 'Demo_Tetrahedron_P.prgm'
Block #44 at offset 8044600 (0x7AC038):
        Block size 744 (0x2E8), data size 737 (0x2E1), header size 20 (0x14)
        Name: 'Demo_TEXTOUT.prgm'
Block #45 at offset 8045344 (0x7AC320):
        Block size 416 (0x1A0), data size 409 (0x199), header size 20 (0x14)
        Name: 'Demo_TEXTOUT_P.prgm'
Block #46 at offset 8045760 (0x7AC4C0):
        Block size 1020 (0x3FC), data size 1014 (0x3F6), header size 20 (0x14)
        Name: 'Demo_TRIANGLE.prgm'
Block #47 at offset 8046780 (0x7AC8BC):
        Block size 904 (0x388), data size 900 (0x384), header size 24 (0x18)
        Name: 'Demo_TRIANGLE_P.prgm'
Block #48 at offset 8047684 (0x7ACC44):
        Block size 168 (0xA8), data size 162 (0xA2), header size 16 (0x10)
        Name: 'Demo_WHILE.prgm'
Block #49 at offset 8047852 (0x7ACCEC):
        Block size 4336 (0x10F0), data size 4331 (0x10EB), header size 12 (0xC)
        Name: 'Eclipse.jpg'
Block #50 at offset 8052188 (0x7ADDDC):
        Block size 752 (0x2F0), data size 747 (0x2EB), header size 24 (0x18)
        Name: 'exam_grad.hpthemepng'
Block #51 at offset 8052940 (0x7AE0CC):
        Block size 27708 (0x6C3C), data size 27702 (0x6C36), header size 12 (0xC)
        Name: 'Garden.jpg'
Block #52 at offset 8080648 (0x7B4D08):
        Block size 513320 (0x7D528), data size 513315 (0x7D523), header size 20 (0x14)
        Name: 'HelpDe.hpresource'
Block #53 at offset 8593968 (0x832230):
        Block size 498060 (0x7998C), data size 498054 (0x79986), header size 20 (0x14)
        Name: 'HelpEn.hpresource'
Block #54 at offset 9092028 (0x8ABBBC):
        Block size 469012 (0x72814), data size 469005 (0x7280D), header size 20 (0x14)
        Name: 'HelpEs.hpresource'
Block #55 at offset 9561040 (0x91E3D0):
        Block size 487260 (0x76F5C), data size 487256 (0x76F58), header size 20 (0x14)
        Name: 'HelpFr.hpresource'
Block #56 at offset 10048300 (0x99532C):
        Block size 384460 (0x5DDCC), data size 384455 (0x5DDC7), header size 20 (0x14)
        Name: 'HelpJa.hpresource'
Block #57 at offset 10432760 (0x9F30F8):
        Block size 482956 (0x75E8C), data size 482951 (0x75E87), header size 20 (0x14)
        Name: 'HelpNl.hpresource'
Block #58 at offset 10915716 (0xA68F84):
        Block size 478236 (0x74C1C), data size 478230 (0x74C16), header size 20 (0x14)
        Name: 'HelpPt.hpresource'
Block #59 at offset 11393952 (0xADDBA0):
        Block size 432056 (0x697B8), data size 432052 (0x697B4), header size 20 (0x14)
        Name: 'HelpRu.hpresource'
Block #60 at offset 11826008 (0xB47358):
        Block size 310244 (0x4BBE4), data size 310239 (0x4BBDF), header size 20 (0x14)
        Name: 'HelpZh.hpresource'
Block #61 at offset 12136252 (0xB92F3C):
        Block size 21032 (0x5228), data size 21028 (0x5224), header size 12 (0xC)
        Name: 'Hexagon.jpg'
Block #62 at offset 12157284 (0xB98164):
        Block size 228 (0xE4), data size 224 (0xE0), header size 16 (0x10)
        Name: 'ISPERFECT.prgm'
Block #63 at offset 12157512 (0xB98248):
        Block size 816 (0x330), data size 812 (0x32C), header size 24 (0x18)
        Name: 'light_grad.hpthemepng'
Block #64 at offset 12158328 (0xB98578):
        Block size 880 (0x370), data size 873 (0x369), header size 24 (0x18)
        Name: 'light_menu.hpthemepng'
Block #65 at offset 12159208 (0xB988E8):
        Block size 37932 (0x942C), data size 37926 (0x9426), header size 12 (0xC)
        Name: 'Louvre.jpg'
Block #66 at offset 12197140 (0xBA1D14):
        Block size 16020 (0x3E94), data size 16016 (0x3E90), header size 16 (0x10)
        Name: 'Nautilus.jpg'
Block #67 at offset 12213160 (0xBA5BA8):
        Block size 192 (0xC0), data size 185 (0xB9), header size 20 (0x14)
        Name: 'PERFECTNUMS.prgm'
Block #68 at offset 12213352 (0xBA5C68):
        Block size 102232 (0x18F58), data size 102228 (0x18F54), header size 20 (0x14)
        Name: 'PrimeSansBold.ttf'
Block #69 at offset 12315584 (0xBBEBC0):
        Block size 4613396 (0x466514), data size 4613392 (0x466510), header size 20 (0x14)
        Name: 'PrimeSansFull.ttf'
Block #70 at offset 16928980 (0x10250D4):
        Block size 42200 (0xA4D8), data size 42196 (0xA4D4), header size 20 (0x14)
        Name: 'PrimeSansMono.ttf'
Block #71 at offset 16971180 (0x102F5AC):
        Block size 5968 (0x1750), data size 5961 (0x1749), header size 12 (0xC)
        Name: 'Rocket.jpg'
Block #72 at offset 16977148 (0x1030CFC):
        Block size 5204 (0x1454), data size 5198 (0x144E), header size 12 (0xC)
        Name: 'Saturn.jpg'
Block #73 at offset 16982352 (0x1032150):
        Block size 21948 (0x55BC), data size 21944 (0x55B8), header size 16 (0x10)
        Name: 'Skatepark.jpg'
Block #74 at offset 17004300 (0x103770C):
        Block size 25664 (0x6440), data size 25660 (0x643C), header size 12 (0xC)
        Name: 'Slices.jpg'
Block #75 at offset 17029964 (0x103DB4C):
        Block size 16804 (0x41A4), data size 16798 (0x419E), header size 12 (0xC)
        Name: 'Spiral.jpg'
Block #76 at offset 17046768 (0x1041CF0):
        Block size 22364 (0x575C), data size 22360 (0x5758), header size 12 (0xC)
        Name: 'Stairs.jpg'
Block #77 at offset 17069132 (0x104744C):
        Block size 27536 (0x6B90), data size 27531 (0x6B8B), header size 12 (0xC)
        Name: 'Stream.jpg'
Block #78 at offset 17096668 (0x104DFDC):
        Block size 18296 (0x4778), data size 18289 (0x4771), header size 12 (0xC)
        Name: 'Theater.jpg'
Block #79 at offset 17114964 (0x1052754):
        Block size 29636 (0x73C4), data size 29630 (0x73BE), header size 12 (0xC)
        Name: 'Tiles.jpg'
Block #80 at offset 17144600 (0x1059B18):
        Block size 5260 (0x148C), data size 5256 (0x1488), header size 12 (0xC)
        Name: 'Tunnel.prgm'


This is my first non-example Go program, and the code is admittedly - and partially intentionally - non-idiomatic.
Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
User avatar
Lionel DebrouxSuper Modo
Niveau 14: CI (Calculateur de l'Infini)
Niveau 14: CI (Calculateur de l'Infini)
Level up: 11.3%
 
Posts: 6865
Joined: 23 Dec 2009, 00:00
Location: France
Gender: Male
Calculator(s):
MyCalcs profile
Class: -
GitHub: debrouxl

Re: HP Prime G2/D rentrée 2018 : spécifications astronomique

Unread postby Lionel Debroux » 20 Aug 2018, 21:50

An updated version, which now stores information - including hashes - in a slice during the initial parsing, and visits this slice for printing and (incomplete) further parsing. Also, it paves the way for more operation modes - taking a clue from imgmanip for the Nspire series.
The code should be somewhat more idiomatic now.

I haven't disassembled the bootloader to RE the format of the binary data in files.sig. SHA-256 is just a wild guess based on the fact that the binary data in files.sig has size ~ (number of files + 1) * size of SHA-256 hash + 0x100, as I wrote above.

Code: Select all
package main

import (
   "bytes"
   "crypto/sha256"
   "encoding/binary"
   "errors"
   "fmt"
   "io"
   "os"
   "strings"
)

func printOutputMessage(msg string) {
   io.WriteString(os.Stdout, msg)
}

func printErrorMessage(msg string) {
   io.WriteString(os.Stderr, msg)
}

func usage() {
   printErrorMessage("HP Prime G2 OS image handling program\nUsage: imgmanip listfields <input file>\nNote: if input file is \"-\", stdin is used instead\n")
   os.Exit(1)
}

func doExitIfError(infile *os.File, i interface{}) {
   if nil != i {
      if nil != infile {
         //printOutputMessage("Closing file\n")
         infile.Close()
      }
      s, ok := i.(string)
      if ok {
         //printOutputMessage("String\n")
         printErrorMessage(s)
      } else {
         e, ok := i.(error)
         if ok {
            //printOutputMessage("Error\n")
            printErrorMessage(e.Error())
         }
      }
      os.Exit(1)
   }
}

func readNBytes(infile *os.File, count uint32) ([]byte, error) {
   var bytes = make([]byte, count)
   nRead, err := io.ReadAtLeast(infile, bytes, len(bytes))
   if nil == err && uint32(nRead) < count {
      err = errors.New("Short read")
   }
   return bytes, err
}

type Block struct {
   id          uint32
   offset      uint32
   blockSize   uint32
   dataSize    uint32
   nameSize    uint32
   name        []byte
   data        []byte
   unknown     []byte
   hash        []byte
   fileSigHash []byte
}

func (block *Block) DisplayBlock() bool {
   fmt.Printf("Block #%d at offset %d (0x%X):\n", block.id, block.offset, block.offset)
   fmt.Printf("\tBlock size %d (0x%X), data size %d (0x%X), header size %d (0x%X)\n",
      block.blockSize, block.blockSize, block.dataSize, block.dataSize, block.nameSize, block.nameSize)
   fmt.Printf("\tName: '%s'\n", block.name)
   return true
}

func visitBlocks(blocks *[]Block, visitFunc func(b *Block) bool) {
   for _, block := range *blocks {
      if !visitFunc(&block) {
         break
      }
   }
}

type FileSigInfo struct {
   name string
   hash []byte
}

type OperationMode uint

const (
   listfields OperationMode = iota
)

func main() {
   // The usual usage information if the program wasn't properly invoked...
   if len(os.Args) < 3 {
      usage()
   }
   var opMode OperationMode
   var infileName string
   var infile *os.File
   var err error
   switch os.Args[1] {
   case "listfields":
      opMode = listfields
      infileName = os.Args[2]
   default:
      usage()
   }
   if infileName != "-" {
      infile, err = os.Open(infileName)
      doExitIfError(infile, err)
   } else {
      infile = os.Stdin
   }

   // Check real file size against embedded file size
   fileInfo, err := infile.Stat()
   doExitIfError(infile, err)
   var realFileSize = fileInfo.Size()

   embeddedFileSizeBytes, err := readNBytes(infile, 4)
   doExitIfError(infile, err)
   var embeddedFileSize = /*encoding.*/ binary.LittleEndian.Uint32(embeddedFileSizeBytes)
   if realFileSize != int64(embeddedFileSize) {
      doExitIfError(infile, "Embedded file size does not match file size\n")
   } else {
      fmt.Printf("File size is %d (0x%X) bytes\n", embeddedFileSize, embeddedFileSize)
   }

   // Now let's loop on the blocks, all of which seem to contain at least 20 bytes.
   var offset uint32 = 4
   var blockID uint32 = 0
   var blocks = make([]Block, 0)
   var blockMap = make(map[string]uint32)
   for offset < embeddedFileSize {
      var remainingBytes = embeddedFileSize - offset
      if remainingBytes < 16 {
         doExitIfError(infile, "Unhandled case 1")
      }

      // Read, parse and display header.
      blockHeader, err := readNBytes(infile, 12)
      doExitIfError(infile, err)
      var blockSize = /*encoding.*/ binary.LittleEndian.Uint32(blockHeader[0:4])
      if blockSize < 20 || blockSize > remainingBytes {
         doExitIfError(infile, fmt.Sprintf("Invalid block size %d for block #%d", blockSize, blockID))
      }
      var dataSize = /*encoding.*/ binary.LittleEndian.Uint32(blockHeader[4:8])
      if dataSize > blockSize || dataSize > remainingBytes {
         doExitIfError(infile, fmt.Sprintf("Invalid data size for block #%d", blockID))
      }
      var nameSize = /*encoding.*/ binary.LittleEndian.Uint32(blockHeader[8:12])
      if nameSize < 4 || nameSize > blockSize || nameSize > remainingBytes-8 {
         doExitIfError(infile, fmt.Sprintf("Invalid name size for block #%d", blockID))
      }
      name, err := readNBytes(infile, nameSize)
      doExitIfError(infile, err)
      unknown, err := readNBytes(infile, 4)
      doExitIfError(infile, err)
      if unknown[0] != 0 || unknown[1] != 0 || unknown[2] != 0 || unknown[3] != 0 {
         doExitIfError(infile, "Unknown data is nonzero")
      }

      // Read data, and deal with it.
      data, err := readNBytes(infile, blockSize-16-nameSize)
      doExitIfError(infile, err)

      var hash = sha256.New()
      hash.Write(blockHeader)
      hash.Write(name)
      hash.Write(unknown)
      hash.Write(data)

      if blockID == 0 && name[0] == 0 {
         name = []byte{'H', 'P', 'P', 'r', 'i', 'm', 'e', '.', 'i', 'm', 'g'}
      } else if blockID == 1 && name[0] == 0 {
         name = []byte{'b', 'o', 'o', 't', 'l', 'o', 'a', 'd', 'e', 'r', '.', 'i', 'm', 'g'}
      }
      // Trim name for easier matching against the contents of file.sig.
      /*if name[0] != 0*/
      {
         name = bytes.TrimFunc(name, func(r rune) bool {
            return r == 0
         })
      }

      blocks = append(blocks, Block{blockID, offset, blockSize, dataSize, nameSize, name, data, unknown, hash.Sum(nil), make([]byte, 0)})
      blockMap[string(name)] = blockID

      // Next block.
      offset += blockSize
      blockID++
   }

   // Display blocks.
   visitBlocks(&blocks, (*Block).DisplayBlock)

   // Parse inside blocks, if necessary.
   visitBlocks(&blocks, func(block *Block) bool {
      fmt.Printf("Block #%d '%s'\n", block.id, block.name)
      fmt.Printf("\tHash: %X\n", block.hash)
      var filesSig = bytes.HasPrefix(block.name, []byte{'f', 'i', 'l', 'e', 's', '.', 's', 'i', 'g'})
      if filesSig {
         var filesCount = /*encoding.*/ binary.LittleEndian.Uint32(block.data[0:4])
         if uint32(len(blocks)) != filesCount+1 {
            doExitIfError(infile, "Unhandled case 2")
         }
         var subBlock1Size = /*encoding.*/ binary.LittleEndian.Uint32(block.data[4:8])
         var subBlock1DataSize = /*encoding.*/ binary.LittleEndian.Uint32(block.data[8:12])
         if subBlock1Size != subBlock1DataSize {
            doExitIfError(infile, "Unhandled case 3")
         }
         if (filesCount+1)*32+0x100+4 != subBlock1Size {
            doExitIfError(infile, "Unhandled case 4")
         }
         var block2Offset = 4 + 4 + subBlock1Size
         // Data format is unknown for now...
         //var subBlock1Data = block.data[4+4:block2Offset] // Re-embed subBlock1DataSize into the sub-block data, these 4 bytes are part of the size
         //fmt.Printf("%X\n", subBlock1Data)
         var subBlock2Size = /*encoding.*/ binary.LittleEndian.Uint32(block.data[block2Offset : block2Offset+4])
         //fmt.Printf("%X\n", subBlock2Size)
         var subBlock2Data = block.data[block2Offset+4 : block2Offset+4+subBlock2Size]
         //fmt.Printf("%X\n", subBlock2Data)
         // Sub-block 2 contains UTF-8 strings without padding.
         var strs = strings.Split(string(subBlock2Data), "\x00")
         if uint32(len(strs)) != filesCount+1 {
            doExitIfError(infile, "Unhandled case 5")
         }
         if strs[len(strs)-1] != "" {
            doExitIfError(infile, "Unhandled case 6")
         }
         // Pop last string, which is empty.
         strs = strs[0 : len(strs)-1]
         fmt.Printf("%d\n", len(strs))
         fmt.Printf("%v\n", strs)
         // TODO RE the data format of sub-block 1 and fill in blocks[blockID].fileSigHash appropriately.
         for _, name := range strs {
            blockID, ok := blockMap[string(name)]
            if !ok {
               doExitIfError(infile, fmt.Sprintf("Entry found in files.sig for unknown '%s' file", name))
            }
            blocks[blockID].fileSigHash = make([]byte, 0)
         }
      }
      // Stop after encountering the files.sig file, we don't parse any other file type for now.
      return !filesSig
   })

   if opMode != listfields {
      // TODO
   }

   infile.Close()
}
Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
User avatar
Lionel DebrouxSuper Modo
Niveau 14: CI (Calculateur de l'Infini)
Niveau 14: CI (Calculateur de l'Infini)
Level up: 11.3%
 
Posts: 6865
Joined: 23 Dec 2009, 00:00
Location: France
Gender: Male
Calculator(s):
MyCalcs profile
Class: -
GitHub: debrouxl

Re: HP Prime G2/D rentrée 2018 : spécifications astronomique

Unread postby Lionel Debroux » 23 Aug 2018, 07:36

I have slightly updated the code in my previous post.

Those who want to load up the code in some RE tool can request that:
* for the OS (HPPrime.img), 0x740118 bytes starting at offset 0x18 be loaded at 0x80000000;
* for the bootloader (bootloader.img), 0x56784 bytes starting at offset 0x740144 be loaded at 0x80000000.

It's clear that at least the boot code contains a software implementation of SHA-256, of which 0x8001C41C is one of the main components. Of course, I don't have the magic values in my head, but the pattern of random binary data mixed with code, in a long code block, is easily noticeable, and a generic search engine query for a single value led me to SHA-256 implementations.
0x8001C41C is called only by 0x8001DCCC, which itself is called only by 0x8001A4CC, called only by 0x8001A566, called only by 0x800147C4, called only by 0x800113B0, which uses the "Error in update." UTF-8 string.
Slightly above that routine, the UTF-8 string " Verifying OS " is pointed to by 0x8001139C, referenced at 0x80010A04. The routine which contains this reference is one of the two callers of 0x800113B0.
Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
User avatar
Lionel DebrouxSuper Modo
Niveau 14: CI (Calculateur de l'Infini)
Niveau 14: CI (Calculateur de l'Infini)
Level up: 11.3%
 
Posts: 6865
Joined: 23 Dec 2009, 00:00
Location: France
Gender: Male
Calculator(s):
MyCalcs profile
Class: -
GitHub: debrouxl

Re: HP Prime G2/D rentrée 2018 : spécifications astronomique

Unread postby Lionel Debroux » 26 Aug 2018, 18:47

On bootloader.img, I've spent a significant amount of time:
* triaging ARM code / Thumb code / strings / data / BSS;
* marking known functions: most yaffs functions, some FreeRTOS functions;
* annotating MRC, MCR and companion (mostly ANDS, ORRS, BICS) instructions.

I wonder whether the trick used by ExtendeD, back in the day, to decrypt the Nspire's OS could be pulled here, in order to help RE the hash checking code in bootloader.img.

BTW, there's also a software RSA implementation in bootloader.img. I just didn't happen to stumble on it at first. There are plenty of references to a rsa.cpp file, which seems to have many lines, judging by the assert messages.
For instance, 0x8001B56C contains such assert messages. It's called by 0x8001A848 (and 0x8001A98E, but that is called only by 0x8001A848), itself called only by 0x8001A3F0, called only by 0x8001A566 - which also calls the SHA256 functions, as mentioned in my above post.

0x8001A3F0 receives from 0x8001A566 a pointer to an interesting data structure, which it passes directly to 0x8001A848. The structure contains the following 32-bit values:
0x800 (2048)
0x100 (256)
0x8003AFA0
0x800417E8
0x0
0x0
0x0
0x0

0x8003AFA0 reads:
* a 32-bit value, 0x40:
* 256 bytes starting at 0x8003AFA4:
0x31, 0x7A, 0x84, 0x92, 0x43, 0x32, 0xA9, 0xD4,
0x78, 0x7C, 0xAF, 0xD3, 0x9C, 0x2E, 0xD0, 0x99,
0x08, 0x09, 0x48, 0x22, 0x5C, 0x59, 0x63, 0xAD,
0xBB, 0xB3, 0xF6, 0x35, 0x3C, 0x9C, 0x51, 0x2E,
0x9A, 0x01, 0xAD, 0xAA, 0x7A, 0x9D, 0x8D, 0x01,
0xE1, 0xA7, 0xC8, 0x66, 0x35, 0xF3, 0x16, 0x43,
0x03, 0xFD, 0xFA, 0x89, 0xEE, 0xA2, 0x77, 0xE8,
0x68, 0xDC, 0x72, 0x48, 0x5F, 0xC5, 0x00, 0x23,
0x33, 0x90, 0x4C, 0xAC, 0xA9, 0x54, 0x74, 0x76,
0x01, 0xBA, 0xDC, 0x33, 0xCF, 0xA8, 0x2B, 0x51,
0xE9, 0x81, 0x44, 0x38, 0x57, 0xD1, 0xC1, 0x53,
0xDA, 0x65, 0x33, 0xA3, 0x53, 0x79, 0xE6, 0xD7,
0x5F, 0xD5, 0x43, 0x70, 0x5C, 0x12, 0xEE, 0x5E,
0x43, 0xAD, 0xF9, 0xA8, 0x3F, 0x3B, 0xAF, 0xA4,
0x80, 0x3C, 0x26, 0xFD, 0xE5, 0xB3, 0x66, 0x85,
0x70, 0xD0, 0xA0, 0x4B, 0x81, 0x86, 0x06, 0xEC,
0xBC, 0xA8, 0xF3, 0xF7, 0xA8, 0xF2, 0xD8, 0xD2,
0x89, 0x8B, 0x32, 0x56, 0x95, 0x7C, 0x5A, 0xC9,
0x19, 0x21, 0x40, 0xE5, 0x56, 0x65, 0x33, 0x4F,
0x07, 0xDD, 0xFE, 0xAC, 0x28, 0xC0, 0xBD, 0xA1,
0x47, 0xDD, 0xAB, 0x91, 0x4A, 0x6C, 0x1C, 0xA9,
0xC2, 0xD8, 0x80, 0x4F, 0x15, 0xDD, 0xCF, 0x7B,
0x3D, 0x6D, 0xAC, 0xFF, 0x5E, 0xE0, 0xA4, 0x8F,
0xBC, 0xEF, 0x8C, 0xCD, 0x5B, 0xF9, 0xBA, 0x8B,
0xD9, 0xBE, 0x0E, 0x7F, 0x0C, 0xE8, 0x7D, 0x03,
0xE1, 0xEA, 0x0B, 0x7A, 0x91, 0xC4, 0x22, 0x7B,
0x1D, 0x68, 0x97, 0x3B, 0xA5, 0xF0, 0x55, 0x43,
0x9C, 0x84, 0x34, 0x9C, 0x46, 0x85, 0xB6, 0x6D,
0x34, 0xB9, 0xAE, 0x16, 0x57, 0x53, 0x75, 0x4A,
0xC4, 0xA1, 0x95, 0xB1, 0xDF, 0x5C, 0x0E, 0xA4,
0xB1, 0x91, 0x35, 0x2B, 0x31, 0x45, 0xDB, 0x16,
0x78, 0x87, 0xCC, 0xC8, 0xD9, 0xD3, 0xA8, 0x92

That may be a size in words, and a 2048-bit RSA key. Again, a wild guess.
Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
User avatar
Lionel DebrouxSuper Modo
Niveau 14: CI (Calculateur de l'Infini)
Niveau 14: CI (Calculateur de l'Infini)
Level up: 11.3%
 
Posts: 6865
Joined: 23 Dec 2009, 00:00
Location: France
Gender: Male
Calculator(s):
MyCalcs profile
Class: -
GitHub: debrouxl

Re: HP Prime G2/D rentrée 2018 : spécifications astronomique

Unread postby critor » 27 Aug 2018, 19:18

critor wrote:Pour info puisqu'il y a quelques intéressés, c'est derekenwinkel.nl qui a livré la G2 dont il est question (voir source) :
https://www.derekenwinkel.nl/rekenmachi ... -1192.html
Mais deux précautions valent mieux qu'une : si vous avez l'intention de commander, mieux vaut les contacter/appeler en précisant bien que vous voulez une G2.
Klaas Kuperus est au courant de la chose.


Pour info, un français me confirme aujourd'hui avoir commandé à la boutique néerlandaise ci-dessus histoire d'être sûr, et avoir bien reçu une G2/D. :bj:
Image
User avatar
critorAdmin
Niveau 19: CU (Créateur Universel)
Niveau 19: CU (Créateur Universel)
Level up: 47.5%
 
Posts: 41980
Images: 15737
Joined: 25 Oct 2008, 00:00
Location: Montpellier
Gender: Male
Calculator(s):
MyCalcs profile
YouTube: critor3000
Twitter: critor2000
GitHub: critor

Re: HP Prime G2/D rentrée 2018 : spécifications astronomique

Unread postby darthvader » 27 Aug 2018, 19:30

Yo Critor :)
ton lien ci dessus ne fonctionne plus ...
Utilise celui ci : https://www.derekenwinkel.nl/rekenmachi ... -1192.html
La théorie c'est quand on sait tout et que rien ne fonctionne ,
La pratique c'est quand tout fonctionne et que personne ne sait pourquoi ;)
User avatar
darthvaderVIP++
Niveau 12: CP (Calculatrice sur Pattes)
Niveau 12: CP (Calculatrice sur Pattes)
Level up: 45.5%
 
Posts: 45
Images: 0
Joined: 06 Dec 2011, 19:53
Location: Moselle
Gender: Male
Calculator(s):
MyCalcs profile
Class: R&D robotique
YouTube: darthphysics

Re: HP Prime G2/D rentrée 2018 : spécifications astronomique

Unread postby critor » 27 Aug 2018, 19:34

Merci. :)
Image
User avatar
critorAdmin
Niveau 19: CU (Créateur Universel)
Niveau 19: CU (Créateur Universel)
Level up: 47.5%
 
Posts: 41980
Images: 15737
Joined: 25 Oct 2008, 00:00
Location: Montpellier
Gender: Male
Calculator(s):
MyCalcs profile
YouTube: critor3000
Twitter: critor2000
GitHub: critor

Re: HP Prime G2/D rentrée 2018 : spécifications astronomique

Unread postby critor » 28 Aug 2018, 19:48

Autre source pour commander des G2 : http://www.studentcalculators.co.uk/aca ... ators.html
Par sécurité, précisez que vous voulez une G2 à James à info@oxford-educational.co.uk .

Source : http://www.hpmuseum.org/forum/thread-11 ... #pid102787
Image
User avatar
critorAdmin
Niveau 19: CU (Créateur Universel)
Niveau 19: CU (Créateur Universel)
Level up: 47.5%
 
Posts: 41980
Images: 15737
Joined: 25 Oct 2008, 00:00
Location: Montpellier
Gender: Male
Calculator(s):
MyCalcs profile
YouTube: critor3000
Twitter: critor2000
GitHub: critor

PreviousNext

Return to News HP

Who is online

Users browsing this forum: ClaudeBot [spider] and 2 guests

-
Search
-
Social TI-Planet
-
Featured topics
Comparaisons des meilleurs prix pour acheter sa calculatrice !
"1 calculatrice pour tous", le programme solidaire de Texas Instruments. Reçois gratuitement et sans aucune obligation d'achat, 5 calculatrices couleur programmables en Python à donner aux élèves les plus nécessiteux de ton lycée. Tu peux recevoir au choix 5 TI-82 Advanced Edition Python ou bien 5 TI-83 Premium CE Edition Python.
Enseignant(e), reçois gratuitement 1 exemplaire de test de la TI-82 Advanced Edition Python. À demander d'ici le 31 décembre 2024.
Aidez la communauté à documenter les révisions matérielles en listant vos calculatrices graphiques !
1234
-
Donations / Premium
For more contests, prizes, reviews, helping us pay the server and domains...
Donate
Discover the the advantages of a donor account !
JoinRejoignez the donors and/or premium!les donateurs et/ou premium !


Partner and ad
Notre partenaire Jarrety Calculatrices à acheter chez Calcuso
-
Stats.
714 utilisateurs:
>682 invités
>22 membres
>10 robots
Record simultané (sur 6 mois):
6892 utilisateurs (le 07/06/2017)
-
Other interesting websites
Texas Instruments Education
Global | France
 (English / Français)
Banque de programmes TI
ticalc.org
 (English)
La communauté TI-82
tout82.free.fr
 (Français)