{"id":850,"date":"2012-06-05T04:27:08","date_gmt":"2012-06-04T20:27:08","guid":{"rendered":"http:\/\/www.computersolutions.cn\/blog\/?p=850"},"modified":"2012-06-05T04:27:08","modified_gmt":"2012-06-04T20:27:08","slug":"jz4755-jamma-board-reverse-engineering-part-2-king-of-game-board","status":"publish","type":"post","link":"https:\/\/www.computersolutions.cn\/blog\/2012\/06\/jz4755-jamma-board-reverse-engineering-part-2-king-of-game-board\/","title":{"rendered":"JZ4755 Jamma Board Reverse Engineering Part 2 (King of Game Board)"},"content":{"rendered":"<p>Continuing on from my last post.<\/p>\n<p>The board I have contains the following hardware (other than the CPU)<\/p>\n<p>RAM &#8211; k4s561632d-tl75 = 16M X 8BITS x 2 banks (64m ram?)<br \/>\nROM &#8211; H27UBG8T2A TR = 4G Nand Flash (4G MLC?  some ref as 2G, need to double check..)<\/p>\n<p>NAND Config:<br \/>\n1024 blocks.  Each block has 256 programmable pages.  Each Page is 8640 bytes (8192+448spare)<\/p>\n<p>Ingenic has a USBBoot.exe tool which can be used to view the NAND.<br \/>\nTesting was done with these nand settings in usbboot.cfg:<\/p>\n<p><code><br \/>\n[PLL]<br \/>\nEXTCLK\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a024\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;Define\u00a0the\u00a0external\u00a0crystal\u00a0in\u00a0MHz<br \/>\nCPUSPEED\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0336\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;Define\u00a0the\u00a0PLL\u00a0output\u00a0frequency<br \/>\nPHMDIV\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a03\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;Define\u00a0the\u00a0frequency\u00a0divider\u00a0ratio\u00a0of\u00a0PLL=CCLK:PCLK=HCLK=MCLK<br \/>\nBOUDRATE\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a057600\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;Define\u00a0the\u00a0uart\u00a0baudrate.  Yes they misspelt it.<br \/>\nUSEUART\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a01\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;Use\u00a0which\u00a0uart,\u00a00\/1\u00a0for\u00a0jz4740,0\/1\/2\/3\u00a0for\u00a0jz4750 <\/p>\n<p>[SDRAM]<br \/>\n\t\t\t\t;k4s561632d \/ : RA0 ~ RA12, Column address : CA 0 ~ CA 8<br \/>\n\t\t\t\t;32M x 2 chips = 64M total Ram.<br \/>\nBUSWIDTH\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a016\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;The\u00a0bus\u00a0width\u00a0of\u00a0the\u00a0SDRAM\u00a0in\u00a0bits\u00a0(16|32)<br \/>\nBANKS\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a04\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;The\u00a0bank\u00a0number\u00a0(2|4)<br \/>\nROWADDR\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a013\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;Row\u00a0address\u00a0width\u00a0in\u00a0bits\u00a0(11-13)<br \/>\nCOLADDR\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a09\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;Column\u00a0address\u00a0width\u00a0in\u00a0bits\u00a0(8-12)<br \/>\nISMOBILE\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a00\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;Define\u00a0whether\u00a0SDRAM\u00a0is\u00a0mobile\u00a0SDRAM,\u00a0this\u00a0only\u00a0valid\u00a0for\u00a0Jz4750\u00a0,1:yes\u00a00:no<br \/>\nISBUSSHARE\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a01\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;Define\u00a0whether\u00a0SDRAM\u00a0bus\u00a0share\u00a0with\u00a0NAND\u00a01:shared\u00a00:unshared <\/p>\n<p>[NAND]<br \/>\nBUSWIDTH\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0    8\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;The\u00a0width\u00a0of\u00a0the\u00a0NAND\u00a0flash\u00a0chip\u00a0in\u00a0bits\u00a0(8|16|32)<br \/>\nROWCYCLES\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0   3\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;The\u00a0row\u00a0address\u00a0cycles\u00a0(2|3)<br \/>\nPAGESIZE\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0    8192\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;The\u00a0page\u00a0size\u00a0of\u00a0the\u00a0NAND\u00a0chip\u00a0in\u00a0bytes(512|2048|4096)<br \/>\nPAGEPERBLOCK\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0256\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;The\u00a0page\u00a0number\u00a0per\u00a0block<br \/>\nFORCEERASE\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0  0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;The\u00a0force\u00a0to\u00a0erase\u00a0flag\u00a0(0|1)<br \/>\nOOBSIZE\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0448\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;oob\u00a0size\u00a0in\u00a0byte<br \/>\nECCPOS\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a00\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;Specify\u00a0the\u00a0ECC\u00a0offset\u00a0inside\u00a0the\u00a0oob\u00a0data\u00a0(0-[oobsize-1])<br \/>\nBADBLACKPOS\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a00\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;Specify\u00a0the\u00a0badblock\u00a0flag\u00a0offset\u00a0inside\u00a0the\u00a0oob\u00a0(0-[oobsize-1])<br \/>\nBADBLACKPAGE\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a00\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;Specify\u00a0the\u00a0page\u00a0number\u00a0of\u00a0badblock\u00a0flag\u00a0inside\u00a0a\u00a0block(0-[PAGEPERBLOCK-1])<br \/>\nPLANENUM\u00a0\u00a0\u00a0\u00a0\u00a0  \u00a0    2\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;The\u00a0planes\u00a0number\u00a0of\u00a0target\u00a0nand\u00a0flash<br \/>\nBCHBIT\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0    4\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;Specify\u00a0the\u00a0hardware\u00a0BCH\u00a0algorithm\u00a0for\u00a04750\u00a0(4|8)<br \/>\nWPPIN\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0   \u00a019\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;Specify\u00a0the\u00a0write\u00a0protect\u00a0pin\u00a0number\u00a0<br \/>\nBLOCKPERCHIP\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a00\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0;Specify\u00a0the\u00a0block\u00a0number\u00a0per\u00a0chip,0\u00a0means\u00a0ignore<br \/>\n<\/code><\/p>\n<p>NAND Config notes &#8211;<\/p>\n<p>HYNIX_H27UBG8T2AR 3.3V 32Gbit NAND<br \/>\n4096M x 8bit<\/p>\n<p> ID of No.0 device No.0 flash: \/\/ ad d7 94 9a 74 42<br \/>\n Vendor ID    :0xad  (Hynix) \/\/Manufacturer Code<br \/>\n Product ID   :0xd7  (Device ID) \/\/ Device Identifier<br \/>\n Chip ID      :0x94  \/\/Internal Chip Number<br \/>\n Page ID      :0x9a  \/\/Page Size\/BlockSize\/Redundant Area<br \/>\n Plane ID     :0x74  \/\/Plane Number , ECC<br \/>\n Tech ID      :0x42 \/\/Tech \/ EDO \/Interface<\/p>\n<p>3.3V Bus Width x8<\/p>\n<p>3rd Byte Dev ID<\/p>\n<p>0x94=0b10010100 <\/p>\n<p>00 &#8211;  Internal Chip Number 1<br \/>\n01 &#8211;  4 Level Cell (cell type)<br \/>\n01 &#8211;  2 pages programmed at once<br \/>\n10 &#8211;  Interleave supported, Write Cache Supported<\/p>\n<p>0x9a=0b10011010<\/p>\n<p>10 &#8211; 8kb page size<br \/>\n0 10 &#8211; 448 Bytes (redundant area size)<br \/>\n1 01 &#8211; 2M Block Size (without spare area)<\/p>\n<p>0x74=0b 0 111 01 00<\/p>\n<p>01 &#8211; 2 Planes<br \/>\nECC level &#8211; reserved.<\/p>\n<p>0x42=0b01 000 010<br \/>\n010 32nm Nand<br \/>\n0 EDO Supported<br \/>\n0 SDR NAND Interface<\/p>\n<p>&#8212;-<\/p>\n<p>I also see this though in one of the nand.cfg files<\/p>\n<p>NandID,NandExtID=PlaneNum, Tals, Talh, \tTrp, Twp,Trhw, Twhr, dwPageSize,   dwBlockSize, dwOOBSize,  dwPageAddressCycle,dwMinValidBlocks,dwMaxValidBlocks,   NandName<\/p>\n<p>0xADD7,0x00749A94=1,\t 15,   \t5,    \t15,  15,  100,   80,  8192,    \t2048*1024,    448, 3,\t 1998,\t2048,\t&#8220;HYNIX_HY27UBG8T2ATR&#8221;}\t<\/p>\n<p>Its referred to there as a 2G sized chip.  So.. are Hynix Docs right or the above?<\/p>\n<p>&#8212;<\/p>\n<p>A look at the NAND shows:<\/p>\n<p>USBBoot :> nreadraw  0 1024 0 0<\/p>\n<p>00000000  ff 55 55 55 55 55 55 55  ff ff ff ff 01 00 11 04  |.UUUUUUU&#8230;&#8230;..|<br \/>\n00000010  00 00 00 00 21 e0 e0 03  00 00 e9 8f 21 e0 20 01  |&#8230;.!&#8230;&#8230;.!. .|<br \/>\n00000020  00 80 1d 3c 00 40 bd 37  00 80 19 3c 90 06 39 27  |&#8230;<.@.7...<..9'|\n00000030  08 00 20 03 00 00 00 00  00 00 00 00 00 00 00 00  |.. .............|\n00000040  1b 43 02 3c 83 de 42 34  19 00 82 00 0f 00 02 3c  |.C.<..B4.......<|\n00000050  10 20 00 00 40 42 42 34  82 24 04 00 1b 00 44 00  |. ..@BB4.$....D.|\n00000060  f4 01 80 00 50 c3 03 34  21 60 a0 00 12 48 00 00  |....P..4!`...H..|\n00000070  1b 00 69 00 f4 01 20 01  12 28 00 00 02 10 25 71  |..i... ..(....%q|\n00000080  01 00 a4 24 50 c3 42 38  0b 28 82 00 04 00 a3 2c  |...$P.B8.(.....,|\n00000090  33 00 60 10 0c 00 a2 2c  04 00 05 24 fc ff a2 24  |3.`....,...$...$|\n000000a0  40 23 02 00 20 4e 02 24  1b 00 49 00 f4 01 20 01  |@#.. N.$..I... .|\n000000b0  12 28 00 00 04 00 a3 2c  27 00 60 14 c0 12 05 00  |.(.....,'.`.....|\n000000c0  08 00 a2 2c 2a 00 40 10  00 18 8a 34 00 5a 05 00  |...,*.@....4.Z..|\n\u2026.\n\nOur JZ4755 is a MIPS XSCALE CPU.\n\nThe above dump is off of a NAND, so we have a 12byte prefix (need to look at the JZ dev nand.c for a proper reason why).\nAllegedly in the spanish forums, its due to NAND write testing for signedness etc.\n\nIf I run it through a decompiler eg mips-linux-objdump -bbinary -mmips -D ..., I do see valid code, so our initial dump looks correct for MIPS.\nMIPS == Backasswardness vs our dump, cough.\n\n0:       555555ff        0x555555ff\n4:       55555555        0x55555555\n8:       ffffffff        0xffffffff\n\nc:       04110001        bal     14 \n10:      00000000        nop\n14:      03e0e021        move    gp,ra\n18:      8fe90000        lw      t1,0(ra)\n1c:      0120e021        move    gp,t1\n20:      3c1d8000        lui     sp,0x8000\n24:      37bd4000        ori     sp,sp,0x4000\n28:      3c198000        lui     t9,0x8000\n2c:      273906b8        addiu   t9,t9,1720\n30:      03200008        jr      t9\n34:      00000000        nop\n38:      00000000        nop\n...\n\nThis should match up to our IPL -> SPL stuff uboot loader.  Lets see, first though, an explanation.<\/p>\n<p>IPL? <\/p>\n<p>IPL = Initial Program Loader.<br \/>\nThis is in CPU, and 8K in size (need to double check that in the Ingenic CPU docs), basically it boots to NAND, runs the code in NAND, unless otherwise directed via boot_sel.<\/p>\n<p>Boot_Sel I hear you ask?<\/p>\n<p>The JZ4755 has an integrated ROM with 8KB this memory is connected to the External Memory Controller (EMC).<br \/>\nAfter a processor reset, the processor runs the program contained in the ROM memory, and depending on the values of the boot_sel[1:0] flags carries out the following operations:<\/p>\n<p>boot_sel[1:0]<br \/>\n00\tUnused<br \/>\n01\tInitialization via USB port: Receives a block of data through the USB (device) port,<br \/>\n        and stores it in internal SRAM.<br \/>\n10\tInitialization via NAND memory with 512-byte pages at Chip Select 1 (CS1):<br \/>\n11\tInitialization via NAND memory with 2048-byte pages at Chip Select 1 (CS1): <\/p>\n<p>Our CPU then reads the first byte from NAND to determine whether the bus is 8- or 16-bit.<br \/>\n(if bit[7:4] = 0, it is 16-bit), and the number of cycles per page is 2 or 3 (if bit[3:0] = 0, it is 2 cycles).<br \/>\nIt then adjusts the EMC using this information and copies the first 8kB from NAND to the internal SRAM.<\/p>\n<p>Our NAND has 8-bit data, 3 cyles, and 8192 bytes per page, so the first byte should be 0xFF<\/p>\n<p>On our board, the boot_sel is configured by the cunningly labelled boot button.<br \/>\nIf its pressed and we then connect a usb cable, our CPU then sits there waiting for an init via USB port.<\/p>\n<p>So, we now know how the board boots up, and why our USB works.<\/p>\n<p>So lets look at the actual boot code we decompiled above.  Luckily I know a man with tar.gz roaming around the back streets, and persuaded him to give me some goodies.  (Ok, fine, its all at the Ingenic.cn ftp site).<\/p>\n<p>I&#8217;ll be even lazier though, and paste in the bits off of the Qi wiki here &#8211; http:\/\/en.qi-hardware.com\/wiki\/Boot_Process as its pretty much identical.<\/p>\n<p>start.S<\/p>\n<p>The first subroutine ran is the _start, which is defined in \/cpu\/mips\/start.S, this subroutine makes a call to the reset function, defined on the same file, which code is shown next:<\/p>\n<p>\t.globl _start<br \/>\n \t.text<br \/>\n        .word JZ4740_NANDBOOT_CFG \/*(0xffffffff) NAND 8 Bits 3 cycles *\/<br \/>\n         b reset; nop    \/* U-boot entry point *\/<br \/>\n         b reset; nop    \/* software reboot *\/<br \/>\nreset:<br \/>\n \t\/*<br \/>\n  \t * CU0=UM=EXL=IE=0, BEV=ERL=1, IP2~7=1 \t *\/<br \/>\n \tli\tt0, 0x0040FC04       \/*t0 = 0x0040FC04 *\/<br \/>\n \tmtc0\tt0, CP0_STATUS       \/*CP0_STAT = 0x0040FC04 Normal mode processor,<br \/>\n                                       disable interrupts, Exception level normal,<br \/>\n                                        kernel mode*\/<br \/>\n \t\/* IV=1, use the specical interrupt vector (0x200) *\/<br \/>\n \tli\tt1, 0x00800000<br \/>\n       \tmtc0\tt1, CP0_CAUSE        \/*CP0_CAUSE = 0x00800000 Cause of last exception*\/<\/p>\n<p>  \t\/* Init Timer *\/<br \/>\n \tmtc0\tzero, CP0_COUNT      \/*Address at which processing resumes after an exception*\/<br \/>\n \tmtc0\tzero, CP0_COMPARE    \/**\/<\/p>\n<p>  \t\/* Initialize GOT pointer.<br \/>\n\t*\/<br \/>\n \tbal     1f<br \/>\n \tnop<br \/>\n \t.word   _GLOBAL_OFFSET_TABLE_<br \/>\n \t1:<br \/>\n \tmove    gp, ra<br \/>\n \tlw      t1, 0(ra)<br \/>\n \tmove\tgp, t1<\/p>\n<p>  \tla\tsp, 0x80004000<br \/>\n \tla\tt9, nand_boot<br \/>\n \tj\tt9<br \/>\n \tnop<\/p>\n<p>Hmm, looks familiar doesn&#8217;t it.<\/p>\n<p>If we look at hex dumps for most nand uboots for this device, you&#8217;ll find fairly similar code structures in all right at the start, albeit with slightly different header prefixes.<\/p>\n<p>Next in series &#8211; dumping the NAND and converting the dumps back to binary for some reverse engineering the file system formats in use (assuming our NAND dumps are indeed correct!).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Continuing on from my last post. The board I have contains the following hardware (other than the CPU) RAM &#8211; k4s561632d-tl75 = 16M X 8BITS x 2 banks (64m ram?) ROM &#8211; H27UBG8T2A TR = 4G Nand Flash (4G MLC? some ref as 2G, need to double check..) NAND Config: 1024 blocks. Each block has [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[390,282,25],"tags":[251,414,391,413,393],"class_list":["post-850","post","type-post","status-publish","format-standard","hentry","category-arcade-machines","category-firmware-2","category-technical-mumbo-jumbo","tag-embedded","tag-ingenic","tag-jamma","tag-mips","tag-reverse-engineering"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/posts\/850","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/comments?post=850"}],"version-history":[{"count":10,"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/posts\/850\/revisions"}],"predecessor-version":[{"id":860,"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/posts\/850\/revisions\/860"}],"wp:attachment":[{"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/media?parent=850"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/categories?post=850"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.computersolutions.cn\/blog\/wp-json\/wp\/v2\/tags?post=850"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}