blob: fe56f6e6e4c2c223a8d669fc10bff9c33d78d016 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
2 * hai_dev.c
3 *
4 * Hardware Abstraction Interface for TFFS on uboot block device.
5 * Interface definition per TFFS requirement, see hai.h by
6 * knightray@gmail.com
7 *
8 * SPDX-License-Identifier: GPL-2.0+
9 */
10#include <common.h>
11#include <part.h>
12#include "pubstruct.h"
13#include "hai_dev.h"
14
15/* This function is adopted from uboot/fs/fat/fat.c:fat_register_device() */
16#define SECTOR_SIZE 512
17#define DOS_PART_TBL_OFFSET 0x1be
18#define DOS_PART_MAGIC_OFFSET 0x1fe
19#define DOS_FS_TYPE_OFFSET 0x36 /* Marvell fixed: this is wrong */
20#define DOS_FS_SS_OFFSET 0xb /* PBR bytes_per_sector offset */
21#define MBR_BOOTABLE_OFFSET 0x1be
22
23static int find_partition(struct tdev_t *pdev)
24{
25 unsigned char buffer[SECTOR_SIZE];
26 disk_partition_t info;
27 block_dev_desc_t *dev_desc = pdev->dev_desc;
28 int part_no = pdev->part_offset;
29 if (!dev_desc->block_read)
30 return -1;
31
32 /* check if we have a MBR (on floppies we have only a PBR) */
33 if (dev_desc->block_read (dev_desc->dev, 0, 1, (ulong *) buffer) != 1) {
34 printf ("** Can't read from device %d **\n", dev_desc->dev);
35 return -1;
36 }
37 if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 ||
38 buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) {
39 /* no signature found */
40 return -1;
41 }
42 /* First we assume, there is a MBR */
43 /* Marvell fixed: PBR has the same magic as MBR:
44 add check for MBR "bootable" field (0 or 0x80 only);
45 add check for PBR bytes_per_sector field */
46 if (!get_partition_info(dev_desc, part_no, &info) && (buffer[MBR_BOOTABLE_OFFSET]&0x7f) == 0) {
47 pdev->part_offset = info.start;
48 } else if ((buffer[DOS_FS_SS_OFFSET] == 0) && (buffer[DOS_FS_SS_OFFSET + 1] == 2)) {
49 /* Sector size 0x200 at offset 0xb: assume PBR */
50 pdev->part_offset = 0;
51 } else {
52 printf ("** Partition %d not valid on device %d **\n",
53 part_no, dev_desc->dev);
54 return -1;
55 }
56 printf("PART offset = %lx\n", pdev->part_offset);
57 return 0;
58}
59
60tdev_handle_t
61HAI_initdevice(
62 IN byte * dev,
63 IN int16 sector_size)
64{
65 struct tdev_t *pdev = (struct tdev_t *)dev;
66
67 pdev->sector_size = sector_size;
68 if (find_partition(pdev))
69 return (tdev_handle_t)NULL;
70 return (tdev_handle_t)dev;
71}
72
73int32
74HAI_readsector(
75 IN tdev_handle_t hdev,
76 IN int32 addr,
77 OUT ubyte * ptr)
78{
79 struct tdev_t *pdev = (struct tdev_t *)hdev;
80
81 if (!ptr || !pdev || !pdev->dev_desc || !pdev->dev_desc->block_read)
82 return ERR_HAI_INVALID_PARAMETER;
83
84 if (pdev->dev_desc->block_read(pdev->dev_desc->dev, addr+pdev->part_offset,
85 1, (unsigned long *)ptr)<0)
86 return ERR_HAI_READ;
87 return HAI_OK;
88}
89
90int32
91HAI_writesector(
92 IN tdev_handle_t hdev,
93 IN int32 addr,
94 IN ubyte * ptr)
95{
96 struct tdev_t *pdev = (struct tdev_t *)hdev;
97
98 if (!ptr || !pdev || !pdev->dev_desc || !pdev->dev_desc->block_write)
99 return ERR_HAI_INVALID_PARAMETER;
100
101 if (pdev->dev_desc->block_write(pdev->dev_desc->dev, addr+pdev->part_offset,
102 1, (unsigned long *)ptr)<0)
103 return ERR_HAI_WRITE;
104 return HAI_OK;
105}
106
107/* Marvell fixed */
108int32
109HAI_writesectors(
110 IN tdev_handle_t hdev,
111 IN int32 addr,
112 IN ubyte * ptr,
113 IN uint32 nsectors)
114{
115 struct tdev_t *pdev = (struct tdev_t *)hdev;
116
117 if (!ptr || !pdev || !pdev->dev_desc || !pdev->dev_desc->block_write)
118 return ERR_HAI_INVALID_PARAMETER;
119
120 if (pdev->dev_desc->block_write(pdev->dev_desc->dev, addr+pdev->part_offset,
121 nsectors, (unsigned long *)ptr)<0)
122 return ERR_HAI_WRITE;
123 return HAI_OK;
124}
125int32
126HAI_closedevice(
127 IN tdev_handle_t hdev)
128{
129 return HAI_OK;
130}
131
132int32
133HAI_getdevinfo(
134 IN tdev_handle_t hdev,
135 OUT tdev_info_t * devinfo)
136{
137 struct tdev_t *pdev = (struct tdev_t *)hdev;
138
139 if (!devinfo || !pdev)
140 return ERR_HAI_INVALID_PARAMETER;
141
142 devinfo->free_sectors = 1000;
143 return HAI_OK;
144}